def _attempt_to_commit(name, level, statute): if (level == "misdemeanor class a" or level == "felony class c") and "attempt to commit" in name: question_string = "Was the underlying conduct a sex crime?" charge_type_by_level = ChargeClassifier._classification_by_level( level, statute).ambiguous_charge_type[0] options = {"Yes": SexCrime(), "No": charge_type_by_level} return ChargeClassifier._build_ambiguous_charge_type_with_question( question_string, options) if level == "felony class b" and "attempt to commit" in name: question_string = "Was this a drug-related charge?" drug_crime_question_string = "Was the underlying substance marijuana?" drug_crime_options = { "Yes": MarijuanaEligible(), "No": FelonyClassB() } drug_crime_classification = ChargeClassifier._build_ambiguous_charge_type_with_question( drug_crime_question_string, drug_crime_options) drug_crime_question_id = f"{question_string}-Yes-{drug_crime_classification.question.question_id}" # type: ignore drug_crime_question = replace(drug_crime_classification.question, question_id=drug_crime_question_id) charge_types = drug_crime_classification.ambiguous_charge_type + [ PersonFelonyClassB() ] question = Question( question_string, question_string, { "Yes": Answer(question=drug_crime_question), "No": Answer(edit={"charge_type": PersonFelonyClassB.__name__}), }, ) return AmbiguousChargeTypeWithQuestion(charge_types, question)
def create(charge_id, **kwargs) -> Tuple[AmbiguousCharge, Optional[Question]]: case_number = kwargs["case_number"] violation_type = kwargs["violation_type"] name = kwargs["name"] statute = ChargeCreator.__strip_non_alphanumeric_chars(kwargs["statute"]) level = kwargs["level"] chapter = ChargeCreator._set_chapter(kwargs["statute"]) section = ChargeCreator.__set_section(statute) disposition = kwargs.get("disposition") ambiguous_charge_type_with_questions = ChargeClassifier( violation_type, name, statute, level, chapter, section, disposition ).classify() kwargs["date"] = datetime.date(datetime.strptime(kwargs["date"], "%m/%d/%Y")) kwargs["_chapter"] = chapter kwargs["_section"] = section kwargs["statute"] = statute kwargs["ambiguous_charge_id"] = f"{case_number}-{charge_id}" classifications = ambiguous_charge_type_with_questions.ambiguous_charge_type question = ambiguous_charge_type_with_questions.question options = ambiguous_charge_type_with_questions.options assert len(classifications) == len(options) if options else True ambiguous_charge = [] options_dict = {} for i, classification in enumerate(classifications): uid = f"{case_number}-{charge_id}-{i}" charge_dict = {**kwargs, "id": uid} charge = from_dict(data_class=classification, data=charge_dict) ambiguous_charge.append(charge) if options: options_dict[options[i]] = uid if question: ambiguous_charge_id = ambiguous_charge[0].ambiguous_charge_id return ambiguous_charge, Question(ambiguous_charge_id, question, options_dict) else: return ambiguous_charge, None
def test_disambiguate_endpoint_with_diverted_answer(record_with_single_duii): ambiguous_record = record_with_single_duii[1] answers = { "CASEJD1-1": Question( ambiguous_charge_id="CASEJD1-1", case_number="CASEJD1", question= "Was the charge dismissed pursuant to a court-ordered diversion program?", options={ "Yes": "CASEJD1-1-0", "No": "CASEJD1-1-1" }, answer="CASEJD1-1-0", ) } questions = json.loads(json.dumps(answers)) unknown_dispositions = record_with_single_duii[3] questions, record = Search.disambiguate_record(ambiguous_record, questions) record_summary = RecordSummarizer.summarize(record, questions, unknown_dispositions) response_data = {"record": record_summary} response_as_dict = json.loads( json.dumps(response_data, cls=ExpungeModelEncoder)) assert response_as_dict == DIVERTED_RESPONSE
def _manufacture_delivery(name, level, statute): if any([ manu_del_keyword in name for manu_del_keyword in ["delivery", "manu/del", "manufactur"] ]): if any([ schedule_2_keyword in name for schedule_2_keyword in ["2", "ii", "heroin", "cocaine", "meth"] ]): if level == "Felony Unclassified": question_string = "Was the charge for an A Felony or B Felony?" options = { "A Felony": FelonyClassA(), "B Felony": FelonyClassB() } return ChargeClassifier._build_ambiguous_charge_type_with_question( question_string, options) elif any([ schedule_3_keyword in name for schedule_3_keyword in ["3", "iii", "4", " iv"] ]): return ChargeClassifier._classification_by_level( level, statute) else: # The name contains either a "1" or no schedule number, and thus is possibly a marijuana charge. question_string = "Was the underlying substance marijuana?" charge_types_with_question = ChargeClassifier._classification_by_level( level, statute) if level == "Felony Unclassified": felony_unclassified_question_id = ( f"{question_string}-No-{charge_types_with_question.question.question_id}" ) felony_unclassified_question = replace( charge_types_with_question.question, question_id=felony_unclassified_question_id) charge_types = [ MarijuanaEligible() ] + charge_types_with_question.ambiguous_charge_type question = Question( question_string, question_string, { "Yes": Answer(edit={ "charge_type": MarijuanaEligible.__name__ }), "No": Answer(question=felony_unclassified_question), }, ) return AmbiguousChargeTypeWithQuestion( charge_types, question) elif level == "Felony Class A" or level == "Felony Class B": charge_type = charge_types_with_question.ambiguous_charge_type[ 0] options = {"Yes": MarijuanaEligible(), "No": charge_type} return ChargeClassifier._build_ambiguous_charge_type_with_question( question_string, options)
def _build_ambiguous_charge_type_with_question( question: str, options: Dict[str, ChargeType]) -> AmbiguousChargeTypeWithQuestion: options_dict = {} charge_types = [] for key, value in options.items(): charge_types.append(value) options_dict[key] = Answer( edit={"charge_type": value.__class__.__name__}) return AmbiguousChargeTypeWithQuestion( charge_types, Question(question, question, options_dict))
def _handle_pcs_and_manufacture_delivery(name, level, statute, schedule_2_handler): if any([ schedule_2_keyword in name for schedule_2_keyword in ["2", "ii", "heroin", "cocaine", "meth"] ]): return schedule_2_handler(level) elif any([ schedule_3_keyword in name for schedule_3_keyword in ["3", "iii", "4", " iv"] ]): return ChargeClassifier._classification_by_level(level, statute) else: # The name contains either a "1" or no schedule number, and thus is possibly a marijuana charge. question_string = "Was the underlying substance marijuana?" charge_types_with_question = ChargeClassifier._classification_by_level( level, statute) if level == "felony unclassified": felony_unclassified_question_id = ( f"{question_string}-No-{charge_types_with_question.question.question_id}" ) felony_unclassified_question = replace( charge_types_with_question.question, question_id=felony_unclassified_question_id) charge_types = [ MarijuanaManufactureDelivery() ] + charge_types_with_question.ambiguous_charge_type question = Question( question_string, question_string, { "Yes": Answer(edit={ "charge_type": MarijuanaManufactureDelivery.__name__ }), "No": Answer(question=felony_unclassified_question), }, ) return AmbiguousChargeTypeWithQuestion(charge_types, question) elif level == "felony class a" or level == "felony class b": charge_type = charge_types_with_question.ambiguous_charge_type[ 0] options = { "Yes": MarijuanaManufactureDelivery(), "No": charge_type } return ChargeClassifier._build_ambiguous_charge_type_with_question( question_string, options)
def test_disambiguate_endpoint_with_diverted_answer(record_with_single_duii): ambiguous_record = record_with_single_duii[1] answers = { "CASEJD1-1": Question( ambiguous_charge_id="CASEJD1-1", question= "Was the charge dismissed pursuant to a court-ordered diversion program?", options={ "Yes": "CASEJD1-1-0", "No": "CASEJD1-1-1" }, answer="CASEJD1-1-0", ) } questions = json.loads(json.dumps(answers)) response = Disambiguate.build_response(ambiguous_record, questions) response_as_dict = json.loads(response) assert response_as_dict == DIVERTED_RESPONSE
def _build_case( oeci_case: OeciCase, new_charges: List[Charge] ) -> Tuple[AmbiguousCase, List[QuestionSummary]]: ambiguous_charges: List[AmbiguousCharge] = [] questions: List[QuestionSummary] = [] for oeci_charge in oeci_case.charges: ambiguous_charge_id = oeci_charge.ambiguous_charge_id charge_dict = { "name": oeci_charge.name, "statute": oeci_charge.statute, "level": oeci_charge.level, "date": oeci_charge.date, "disposition": oeci_charge.disposition, "probation_revoked": oeci_charge.probation_revoked, "balance_due_in_cents": oeci_charge.balance_due_in_cents, "case_number": oeci_case.summary.case_number, "violation_type": oeci_case.summary.violation_type, "birth_year": oeci_case.summary.birth_year, "edit_status": EditStatus(oeci_charge.edit_status), } if oeci_charge.disposition.status == DispositionStatus.UNKNOWN: charge_dict.pop("disposition") ambiguous_charge_dismissed, question_dismissed = ChargeCreator.create( ambiguous_charge_id, **charge_dict, disposition=DispositionCreator.create( date_class.today(), "dismissed"), ) ambiguous_charge_convicted, question_convicted = ChargeCreator.create( ambiguous_charge_id, **charge_dict, disposition=DispositionCreator.create( date_class.future(), "convicted"), ) if RecordCreator._disposition_question_is_irrelevant( ambiguous_charge_convicted, ambiguous_charge_dismissed): ambiguous_charges.append(ambiguous_charge_dismissed) question = RecordCreator._append_ambiguous_charge_id_to_question_id( question_dismissed, ambiguous_charge_id ) if question_dismissed else None # type: ignore # TODO: Fix type else: ambiguous_charges.append(ambiguous_charge_dismissed + ambiguous_charge_convicted) disposition_question_text = "Choose the disposition" question_id_prefix = ambiguous_charge_id + disposition_question_text dismissed_option = RecordCreator._build_option( question_dismissed, "Dismissed", f"{question_id_prefix}-dismissed") convicted_option = RecordCreator._build_option( question_convicted, "Convicted", f"{question_id_prefix}-convicted") probation_revoked_option = RecordCreator._build_probation_revoked_option( question_convicted, f"{question_id_prefix}-revoked") unknown_option = {"Unknown": Answer()} question = Question( question_id_prefix, disposition_question_text, { **dismissed_option, **convicted_option, **probation_revoked_option, **unknown_option }, ) else: ambiguous_charge, maybe_question = ChargeCreator.create( ambiguous_charge_id, **charge_dict) ambiguous_charges.append(ambiguous_charge) question = RecordCreator._append_ambiguous_charge_id_to_question_id( maybe_question, ambiguous_charge_id ) if maybe_question else None # type: ignore # TODO: Fix type if question: question_summary = QuestionSummary( ambiguous_charge_id, oeci_case.summary.case_number, question) questions.append(question_summary) ambiguous_charges += [[charge] for charge in new_charges] ambiguous_case: AmbiguousCase = [] for charges in product(*ambiguous_charges): possible_case = Case(oeci_case.summary, charges=tuple(charges)) ambiguous_case.append(possible_case) return ambiguous_case, questions