def __init__(self): self.chain = TranslationChain() # 基本sql语句, 供翻译方法使用 self.sql_Y_status = 'match (y:Year) where y.name="{y}" return y.info' self.sql_C_status = 'match (y:Year)-[r:info]->(c:Catalog) where y.name="{y}" and c.name="{c}" return r.info' self.sql_I_value = 'match (y:Year)-[r:value]->(i:Index) where y.name="{y}" and i.name="{i}" return r.value,r.unit' self.sql_A_value = 'match (y:Year)-[r:`{i}`]->(n:Area) where y.name="{y}" and n.name="{a}" return r.value,r.unit,r.repr' self.sql_find_I_parent = 'match (n:Index)-[r:contain]->(m:Index) where m.name="{i}" return n.name,r.life' self.sql_find_A_parent = 'match (n:Area)-[r:contain]->(m:Area) where m.name="{a}" return n.name,r.life' self.sql_find_I_child = 'match (n:Index)-[r]->(m) where n.name="{i}" return m.name,labels(m)[0],r.life' self.sql_find_Is = 'match (y:Year)-[r:value]->(i:Index) where y.name="{y}" return i.name' self.sql_find_Cs = 'match (y:Year)-[r:include]->(c:Catalog) where y.name="{y}" return c.name' self.sql_find_begin_stats_Ys = 'match (y:Year)-[r:value]->(i:Index) where i.name="{i}" return y.name'
def _search_direct_then_feed(self, chain: TranslationChain, unpack_key_name: str) -> tuple: """ 将第一次直接查询的结果作为第二次查询的输入 """ results_1 = self._search_direct(chain) pattern_sql = next(chain.iter(1)) sqls = [] for items in results_1: if not items: sqls.append(None) continue for item in items: sqls.append(pattern_sql.format(item[unpack_key_name])) results_2 = self._search_direct(sqls) return results_1, results_2
def _search_double_direct_then_feed(self, chain: TranslationChain, unpack_key_name: str) -> tuple: """ 第一次直接查询,第二次先执行直接查询后将查询结果投递至最后的查询 """ results_1 = self._search_direct(chain) temp_res = self._search_direct(chain, 1) sqls = [] for feed in temp_res: for pattern_sql in chain.iter(2): if feed is None: sqls.append(None) continue sqls.append(pattern_sql.format(feed[0][unpack_key_name])) results_2 = self._search_direct(sqls) return results_1, results_2, temp_res
def _search_double_direct_then_feed(self, chain: TranslationChain, unpack: bool = False) -> tuple: """ 第一次直接查询,第二次先执行直接查询后将查询结果投递至最后的查询 """ results_1 = self._search_direct(chain, unpack=unpack) temp_res = self._search_direct(chain, 1) final_sqls = [] for feed in temp_res: sqls = [] for pattern_sql in chain.iter(2, unpack=unpack): if not feed: sqls.append(None) continue sqls.append(pattern_sql.format(feed.name)) final_sqls.append(sqls) results_2 = self._search_direct(final_sqls) return results_1, results_2, temp_res
class QuestionParser: def __init__(self): self.chain = TranslationChain() # 基本sql语句, 供翻译方法使用 self.sql_Y_status = 'match (y:Year) where y.name="{y}" return y.info' self.sql_C_status = 'match (y:Year)-[r:info]->(c:Catalog) where y.name="{y}" and c.name="{c}" return r.info' self.sql_C_exist = 'match (y:Year)-[r:include]->(c:Catalog) where y.name="{y}" return c.name' self.sql_I_value = 'match (y:Year)-[r:value]->(i:Index) where y.name="{y}" and i.name="{i}" return r.value,r.unit' self.sql_A_value = 'match (y:Year)-[r:`{i}`]->(n:Area) where y.name="{y}" and n.name="{a}" return r.value, r.unit,r.repr' self.sql_find_I_parent = 'match(n:Index)-[r:contain]->(m:Index) where m.name="{i}" return n.name' self.sql_find_A_parent = 'match(n:Area)-[r:contain]->(m:Area) where m.name="{a}" return n.name' self.sql_find_I_child = 'match(n:Index)-[r:contain]->(m:Index) where n.name="{i}" return m.name' self.sql_find_A_I = 'match (i:Index)-[r:locate]->(a:Area) where i.name="{i}" return a.name' self.sql_find_Is = 'match (y:Year)-[r:value]->(i:Index) where y.name="{y}" return i.name' self.sql_find_Cs = 'match (y:Year)-[r:include]->(c:Catalog) where y.name="{y}" return c.name' self.sql_find_begin_stats_Ys = 'match (y:Year)-[r:value]->(i:Index) where i.name="{i}" return y.name' def parse(self, result: Result) -> Result: for qt in result.question_types: # 查询语句翻译 if qt == 'year_status': self.trans_year_status(result['year']) elif qt == 'catalog_status': self.trans_catalog_status(result['year'], result['catalog']) elif qt == 'exist_catalog': self.trans_exist_catalog(result['year']) elif qt in ('index_value', 'indexes_m_compare', 'indexes_n_compare'): self.trans_index_value(result['year'], result['index']) elif qt == 'index_overall': self.trans_index_overall(result['year'], result['index']) elif qt in ('index_2_overall', 'indexes_overall_trend'): self.trans_indexes_overall(result['year'], result['index']) elif qt == 'index_compose': self.trans_index_compose(result['year'], result['index']) elif qt in ('indexes_2m_compare', 'indexes_2n_compare'): self.trans_indexes_mn_compare(result['year'], result['index']) elif qt == 'indexes_g_compare': self.trans_indexes_g_compare(result['year'], result['index']) elif qt in ('area_value', 'areas_m_compare', 'areas_n_compare'): self.trans_area_value(result['year'], result['area'], result['index']) elif qt == 'area_overall': self.trans_area_overall(result['year'], result['area'], result['index']) elif qt in ('area_2_overall', 'areas_overall_trend'): self.trans_areas_overall(result['year'], result['area'], result['index']) elif qt == 'area_compose': self.trans_area_compose(result['year'], result['index']) elif qt in ('areas_2m_compare', 'areas_2n_compare'): self.trans_areas_mn_compare(result['year'], result['area'], result['index']) elif qt == 'areas_g_compare': self.trans_areas_g_compare(result['year'], result['area'], result['index']) elif qt in ('indexes_trend', 'indexes_max'): self.trans_indexes_value(result['year'], result['index']) elif qt in ('areas_trend', 'areas_max'): self.trans_areas_value(result['year'], result['area'], result['index']) elif qt in ('index_change', 'indexes_change'): self.trans_index_change(result['year']) elif qt in ('catalog_change', 'catalogs_change'): self.trans_catalog_change(result['year']) elif qt == 'begin_stats': self.trans_begin_stats(result['index']) result.add_sql(qt, deepcopy(self.chain)) self.chain.reset() return result # 年度总体状况 def trans_year_status(self, years): self.chain.make([self.sql_Y_status.format(y=years[0])]) # 年度目录状况 def trans_catalog_status(self, years, catalogs): self.chain.make( [self.sql_C_status.format(y=years[0], c=c) for c in catalogs]) # 指标变化情况 def trans_index_change(self, years): self.chain.make([self.sql_find_Is.format(y=y) for y in years]) # 目录变化情况 def trans_catalog_change(self, years): self.chain.make([self.sql_find_Cs.format(y=y) for y in years]) # 年度目录包含哪些 def trans_exist_catalog(self, years): self.chain.make([self.sql_C_exist.format(y=years[0])]) # 指标值 def trans_index_value(self, years, indexes): self.chain.make( [self.sql_I_value.format(y=years[0], i=i) for i in indexes]) # 多个年份指标值变化趋势 def trans_indexes_value(self, years, indexes): self.chain.make([[self.sql_I_value.format(y=y, i=i) for y in years] for i in indexes]) # 两个年份下的指标值的各种比较 def trans_indexes_mn_compare(self, years, indexes): self.chain.make([[self.sql_I_value.format(y=y, i=i) for y in years] for i in indexes]) # 指标值同比比较 def trans_indexes_g_compare(self, years, indexes): last_year = int(years[0]) - 1 QuestionYearOverstep.check(last_year) self.chain.make([[ self.sql_I_value.format(y=last_year, i=i), self.sql_I_value.format(y=years[0], i=i) ] for i in indexes]) # 指标占总比 def trans_index_overall(self, years, indexes): self.chain.make([self.sql_I_value.format(y=years[0], i=i) for i in indexes])\ .then([self.sql_find_I_parent.format(i=i) for i in indexes])\ .then([self.sql_I_value.format(y=years[0], i='{}')]) # 两或多个年份指标占总比的变化 def trans_indexes_overall(self, years, indexes): self.chain.make([[self.sql_I_value.format(y=y, i=i) for y in years] for i in indexes])\ .then([self.sql_find_I_parent.format(i=i) for i in indexes])\ .then([self.sql_I_value.format(y=y, i='{}') for y in years]) # 指标组成 def trans_index_compose(self, years, indexes): self.chain.make([self.sql_find_I_child.format(i=i) for i in indexes])\ .then([self.sql_I_value.format(y=years[0], i='{}')]) # 地区指标值 def trans_area_value(self, years, areas, indexes): self.chain.make([ self.sql_A_value.format(y=years[0], i=i, a=a) for a in areas for i in indexes ]) def trans_areas_value(self, years, areas, indexes): self.chain.make( [[[self.sql_A_value.format(y=y, i=i, a=a) for y in years] for a in areas] for i in indexes]) # 两个年份下地区的指标值的各种比较 def trans_areas_mn_compare(self, years, areas, indexes): self.chain.make( [[[self.sql_A_value.format(y=y, a=a, i=i) for y in years] for a in areas] for i in indexes]) # 地区指标值同比比较 def trans_areas_g_compare(self, years, areas, indexes): last_year = int(years[0]) - 1 QuestionYearOverstep.check(last_year) self.chain.make([[ self.sql_A_value.format(y=last_year, a=areas[0], i=i), self.sql_A_value.format(y=years[0], a=areas[0], i=i) ] for i in indexes]) # 地区指标占总比 def trans_area_overall(self, years, areas, indexes): self.chain.make([self.sql_A_value.format(y=years[0], i=i, a=a) for a in areas for i in indexes])\ .then([self.sql_find_A_parent.format(a=a) for a in areas])\ .then([self.sql_A_value.format(y=years[0], i=i, a='{}') for i in indexes]) # 地区两或多个年份指标占总比的变化 def trans_areas_overall(self, years, areas, indexes): self.chain.make([[[self.sql_A_value.format(y=y, i=i, a=a) for y in years] for a in areas] for i in indexes])\ .then([self.sql_find_A_parent.format(a=a) for a in areas])\ .then([[self.sql_A_value.format(y=y, i=i, a='{}') for y in years] for i in indexes]) # 地区指标组成 def trans_area_compose(self, years, indexes): self.chain.make([self.sql_find_A_I.format(i=i) for i in indexes])\ .then([self.sql_A_value.format(y=years[0], i=i, a='{}') for i in indexes]) # 何时开始统计此项指标 def trans_begin_stats(self, indexes): self.chain.make( [self.sql_find_begin_stats_Ys.format(i=i) for i in indexes])
def make_index_compose_ans(self, answer: Answer, builder: AnswerBuilder, chain: TranslationChain, result: Result): data = self._search_direct(chain) builder.feed_data(data) collect = [] units = [] sub_titles = [] # for overall sqls_overall = [sql for sql in chain.iter(3)] data_overall = self._search_direct(sqls_overall) # collect for total, (item, name) in zip( data_overall, builder.product_data_with_name(result['index']) ): # 为使两可迭代对象同步迭代和collect不用做判空,此处不使用if_is_none参数 if not item: answer.add_answer(f'指标“{name.name}”没有任何组成') continue indexes, areas = [], [] for n in item: n.life_check(result['year'][0]) if n: if n.label == 'Index': indexes.append(n.name) else: areas.append(n.name) if len(indexes) == 0 and len(areas) == 0: answer.add_answer(f'指标“{name.name}”没有任何组成') continue # for indexes sqls1 = [sql.format(i) for sql in chain.iter(1) for i in indexes] data1 = self._search_direct(sqls1) # for areas sqls2 = [sql.format(name.name, a) for sql in chain.iter(2) for a in areas] data2 = self._search_direct(sqls2) # make data pairs final_data = {} for k, v in zip(indexes + areas, data1 + data2): if not v: continue if v.child_id is None: continue try: final_data.setdefault(v.child_id, []).append((k, float(v.value))) except ValueError or TypeError: answer.add_answer(f'{name.name}中{k}的记录非数值类型,无法比较') return # make other for k, v in final_data.items(): op1 = sum([x[1] for x in v]) op2 = float(total.value) if op1 < int(op2): # 舍弃一些误差,避免图中出现极小的部分 final_data[k].append(('其他', round(op2 - op1, 2))) collect.append(final_data) units.append(total.unit) sub_titles.append(f'{name.subject()}为{total.val()},其构成分为:') # paint for pie in self.painter.paint_pie(collect, units, title=result.raw_question, sub_titles=sub_titles): answer.save_chart(pie) answer.add_answer(f'该问题的回答已渲染为图像,详见:{CHART_RENDER_DIR}/{result.raw_question}.html')