Beispiel #1
0
    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'
Beispiel #2
0
 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
Beispiel #3
0
 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
Beispiel #4
0
 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
Beispiel #5
0
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])
Beispiel #6
0
 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')