def BottomBox(data): return Row( width='100%', margin=Rect([8, 0, 6, 0]), border=Border( width=0.5, color=Color.BLACK, ), padding=Rect([2, 8, 4, 8]), ).add( Column(width='50%').add( Text( text=boil('status_of_cm_types_of_workers'), font_family='Roboto Condensed', font_size=8, font_weight=Pango.Weight.BOLD, ), Text(text='{} {}'.format( boil('status_of_cm_list_1'), boil('status_of_cm_skilled_mason'), ), font_family='Roboto Condensed', font_size=8, padding=Rect([2, 0, 2, 0])), Text( text='{} {}'.format( boil('status_of_cm_list_2'), boil('status_of_cm_labourer'), ), font_family='Roboto Condensed', font_size=8, ), ), Column(width='60%').add( Text( text=boil('status_of_cm_avg._daily_wage_(nrs.)'), width='100%', alignment=Text.CENTER, font_family='Roboto Condensed', font_size=8, font_weight=Pango.Weight.BOLD, ), Text( text='%s %s' % (fmt_num(data['avg_wage_1']), '/-'), width='65%', alignment=Text.RIGHT, font_family='Roboto Condensed', font_size=8, padding=Rect([2, 0, 2, 0]), ), Text( text='%s %s' % (fmt_num(data['avg_wage_2']), '/-'), width='65%', alignment=Text.RIGHT, font_family='Roboto Condensed', font_size=8, padding=Rect([0, 0, 1, 0]), )), )
def Header(data): nm_text = '{} | {}'.format( data['rep_data']['dist_nm'], data['rep_data']['palika_nm'], ) return Column( width='100%', margin=Rect([0, 5, 8, 5]), ).add( Row(height=52, width='10%').add( Text( text=boil('header_title'), font_family='Roboto Condensed', font_size=24, font_weight=Pango.Weight.BOLD, color=Color.PRIMARY, height='100%', vertical_alignment=Text.BOTTOM, ), Vr( width=2, height='100%', color=Color.PRIMARY, margin=Rect([0, 16, 0, 16]), padding=Rect([24, 0, 0, 0]), ), Column(height='100%', justify='end').add( Text( text='{} {}'.format( boil('header_month'), boil('header_year') if isinstance( boil('header_year'), str) else get_lang_num( str(boil('header_year'))), ), font='Roboto Light', font_size=10, color=Color.PRIMARY, ), Text( text=nm_text, font='Roboto Light', font_size=calc_nm_len(nm_text), color=Color.PRIMARY, ))), Hr( width='100%', height=1, color=Color.PRIMARY, margin=Rect([8, 0, 0, 0]), ), Hr( width='100%', height=1.8, color=Color.PRIMARY, margin=Rect([2, 0, 0, 0]), ), )
def Pop(data): for k, v in data.items(): if not v: data[k] = boil('partner_orgs_no_partner_orgs') hs = _calc_box_hs([v for v in data.values()]) return Column(width='100%', height='100%').add( Column( width='100% - 16', height='76%', margin=Rect([12, 8, 4, 11]), ).add(*[PoGroup(info[0], info[1]) for info in zip(hs, data.items())]))
def ReconstructionAndRetrofit(data): return Row(width='100%', padding=Rect(8)).add( Column(width='50%', padding=Rect([3, 8, 0, 2])).add( ReconstructionStatus(data['reconstruction_status']), Houses(data['houses']), ), Column(width='50%', padding=Rect([3, 2, 0, 8])).add( RetrofitStatus(data['retrofitting_status']), Row(width='100%').add( Grievances(data['grievances']), NonCompliance(data['non_compliances']), ), ))
def Page(data): return Column(width='100%', relative=True).add( Row(width='100%').add( Panel( title=boil('facts_and_figures_panel_title'), height=148, width='50% - 5', ).add(FF(data['facts_and_figures'])), Panel( title=boil('typologies_panel_title'), height=148, width='50% - 5', ).add(Typologies(data['housing_typologies'])), ), Row(width='100%').add( Panel( title=boil('recon_&_retrofit_panel_title'), width='100%', right_footer=ReconstructionAndRetrofitFooter, footer_data=data['reconstruction_retrofit_updates'] ['recon_footer_date'], ).add( ReconstructionAndRetrofit( data['reconstruction_retrofit_updates']), ), ), Row(width='100%').add( Column(width='50%', height='100%').add( Panel( title=boil('po_presence_pos_presence_title'), height='45% - 20', width='100% - 10', ).add(Pop(data['pos_presence'])), Panel( title=boil('other_sectors_panel_title'), height='55% - 20', width='100% - 10', ).add(OtherSectors(data['other_sectors'])), ), Panel( title=boil('status_of_cm_panel_title'), width='50%', ).add(CMTable(data['construction_materials'], data['work_wage'])), ), Panel( title=boil('key_contacts_panel_title'), width='100%', left_footer=LeftFootNotes, right_footer=RightFootNotes, ).add(KeyContacts(data['key_contacts']), ), Sidebar(bottom=0, left=-12), )
def Contact(it, title, contact): for k, v in contact.items(): # TODO: fix 'none' if not v or v == 'None': contact[k] = '-' return Column(width='33%', padding=Rect([0, 8, 0, 8])).add( Text( text=title, font_family="Roboto Condensed", font_size=9, font_weight=Text.BOLD, ), Text( text=contact['name'] if contact['name'] != ZERO_DEFAULT else '', font_family="Roboto Condensed", font_size=7, ), Text( text=contact['title'] if contact['title'] != ZERO_DEFAULT else '', font_family="Roboto Condensed", font_size=7, ), Text( text=get_lang_num(contact['contact']) if contact['contact'] != ZERO_DEFAULT else '', font_family="Roboto Condensed", font_size=7, ))
def Sector(label, items, icon): return Column( width='50%', height='100%', justify='center', align='center', ).add( Canvas( width=56, height=56, renderer=IconRenderer(filename=icon), ), Text( text=label, color=Color.ACCENT, margin=Rect(4), font_family='Roboto Condensed', font_size=8, font_weight=Pango.Weight.BOLD, ), *[ Row().add( Text( text='{}: '.format(key), font_family='Roboto Condensed', font_size=8, font_weight=Pango.Weight.BOLD, ), Text( text=value, font_family='Roboto Condensed', font_size=8, )) for key, value in items.items() ])
def NonCompliance(data): return Column(width='50%').add( Text( text=boil('recon_&_retrofit_non-compliances_title'), color=Color.ACCENT, font_family="Roboto Condensed", font_size=9, font_weight=Text.BOLD, margin=Rect([3.2, 0, 5, 0]), ), Text(markup='<b>{}:</b> {}'.format( boil('recon_&_retrofit_registered_(both)'), fmt_num(data['registered']), ), font_family="Roboto Condensed", font_size=7.5, margin=Rect([0, 0, 3, 0])), Text( markup='<b>{}:</b> {}'.format( boil('recon_&_retrofit_addressed_(both)'), fmt_num(data['addressed']), ), font_family="Roboto Condensed", font_size=7.5, ), )
def RetrofitStatus(data): rows = [ TwoValueLineChart(datum, bar_color=Color.ACCENT2) for datum in data ] return Column(width='100%').add( Text( text=boil('recon_&_retrofit_retrofitting_status_title'), font_family="Roboto Condensed", font_size=9, font_weight=Text.BOLD, color=Color.ACCENT, ), Hr( width='100%', height=1, margin=Rect([3, 0, 3, 0]), dash=[3], color=Color.PRIMARY, ), *rows, Hr( width='100%', height=1, margin=Rect([3, 0, 3, 0]), dash=[3], color=Color.PRIMARY, ), )
def Houses(data): return Column(width='100%').add( Text(text=boil('recon_&_retrofit_houses_title'), font_family="Roboto Condensed", font_size=9, font_weight=Text.BOLD, color=Color.ACCENT, margin=Rect([0, 0, 2, 0])), Row( width='100%', justify='space-between', margin=Rect([0, 0, 3, 0]), ).add( Text( markup='<b>{}</b>: {}'.format( boil('recon_&_retrofit_under_construction'), fmt_num(data['under_construction'], )), font_family="Roboto Condensed", font_size=7.5, ), Text( markup='<b>{}</b>: {}'.format( boil('recon_&_retrofit_completed'), fmt_num(data['completed'], )), font_family="Roboto Condensed", font_size=7.5, )), )
def FurtherInfoNotes(data, **kwargs): # TODO: check nans before entering return Row(**kwargs, width='100%', height=16).add( Text( text=boil('page_2_futher_information'), font_family='Roboto Condensed', font_size=7, font_weight=Pango.Weight.BOLD, padding=Rect([12.5, 0, 0, 5]), ), *[ Column(padding=Rect(8)).add( Text( text='{}. {} ({})'.format( get_lang_num(i + 1), contact['name'] if contact['name'] and contact['name'] != 'None' else '', contact['title'] if contact['title'] and contact['title'] != 'None' else '', ), font_family='Roboto Condensed', font_size=7, padding=Rect([5, 0, 0, 0]), ), Text( text=' {}'.format( get_lang_num(contact['phone']) if contact['phone'] and contact['phone'] != 'None' else ''), font_family='Roboto Condensed', font_size=7, ), ) for i, contact in enumerate(data) if not all([is_nan(v) for v in contact.values()]) ])
def PoGroup(h, pos): #TODO: set global val for what blank is label = pos[0] pos_list = pos[1] return Column( width='98%', height='{}%'.format(h + 4), border=Border( width=0.5, color=Color.BLACK, ), ).add( Text( width='98%', height='{}%'.format(h + 4), # markup='{}'.format('hello '*60), markup='<b>{}:</b> {}'.format(boil(label), pos_list), color=Color.BLACK, font_family="Roboto Condensed", font_size=7, #TODO: fix bug where row cuts off early auto_scale_height=False, padding=Rect([1, 0, 5, 3]), ), )
def Page2(data, LANG): set_lang(LANG) return Column( width=WIDTH, height=HEIGHT, bg_color=Color.WHITE, padding=Rect(32), ).add(Page2Content(data), )
def Footer(data): faq_blocks = [] for it, item in enumerate(data): question = Text( width='100%', text='{}: {}'.format(boil('faq_q'), item['q']), font_family='Roboto Condensed', font_size=8.5, font_weight=Pango.Weight.BOLD, ) answer = Text( width='100%', text='{}: {}'.format(boil('faq_a'), item['a']), font_family='Roboto Condensed', font_size=8, padding=Rect([0, 0, 8, 0]) if it == 0 else Rect(0), ) faq_blocks.append(question) faq_blocks.append(answer) return Column( width='100%', padding=Rect([10, 16, 6, 16]), ).add(*faq_blocks, )
def Page(data): return Column(width='100%', relative=True).add( Panel( title=boil('land_issues_panel_title'), width='100% - 10', ).add(HH(data['hhs'])), Row(width='100%').add( Panel( title=boil('tech_staff_panel_title'), height='100% - 20', width='50% - 10', right_footer=TechnicalStaffFooter, ).add( TechnicalStaff( data['technical_staff'], data['technical_staff_masons'], )), Panel( title=boil('training_panel_title'), height='100% - 20', width='50% - 10', right_footer=TrainingsFooter, ).add(Trainings(data['trainings'])), ), Panel( title=boil('map_panel_title'), width='100% - 10', ).add(Map(data['map'])), Panel( title=boil('faq_panel_title'), width='100% - 10', left_footer=FurtherInfoNotes, footer_data=data['further_info'], ).add(Footer(data['faq'])), Sidebar(bottom=0, right=-12), )
def KeyContacts(data): titles = [boil('key_contacts_municipal_office_title')] * 4 + [ boil('key_contacts_gmali/nra_title'), boil('key_contacts_dlpiu-building_title'), ] return Column( width='100%', margin=Rect([0, 5, 0, 0]), ).add( Row( width='100%', padding=Rect([15, 0, 20, 0]), ).add(*[ Contact(i, titles[i], contact) for i, contact in enumerate(data[:3]) ])).add( Row( width='100%', padding=Rect([0, 0, 12, 0]), ).add(*[ Contact(i + 3, titles[i + 3], contact) for i, contact in enumerate(data[3:]) ]))
def HH(data): """for showing the HH bar. logic: if 0 values: show message that there are no reported issues if 1 value: do something #TODO else: show bar """ # info f.e type items = [ { 'key': 'landless', 'label': boil('land_issues_landless'), 'color': hx('#ff6117'), }, { 'key': 'no_land_certificates', 'label': boil('land_issues_no_land_certificates'), 'color': hx('#bf053d'), }, { 'key': 'right_of_way', 'label': boil('land_issues_right_of_way'), 'color': hx('#7d0547'), }, { 'key': 'affected_by_hep', 'label': boil('land_issues_affected_by_hep'), 'color': hx('#1e7a8c'), }, { 'key': 'smallplots', 'label': boil('land_issues_small_plots'), 'color': hx('#abd1b5'), }, { 'key': 'guthi_land', 'label': boil('land_issues_guthi_land'), 'color': hx('#ffc202'), }, ] # add val and drop item if it's zero or invalid items = _filter_items(items, data) wdz = _get_widths(items) bars = [] labels = [] if wdz: for item in wdz: color = item['color'] bar = Text( bg_color=color, height=20, width='{}%'.format(item['w']), alignment=Text.CENTER, vertical_alignment=Text.MIDDLE, text=fmt_num(item['val']), color=Color.WHITE, font_family='Roboto Condensed', font_size=11, font_weight=Pango.Weight.BOLD, ) bars.append(bar) label = Label( label=item['label'], color=color, ) labels.append(label) return Column( width='100%', padding=Rect([16, 16, 8, 16]), ).add( Row(width='100%').add(*bars), Row( width='100%', justify='space-between' if len(labels) > 1 else None, ).add(*labels) ) else: return Column(width='100%', height='100%').add( Text( height='100%', width='100%', alignment=Text.CENTER, vertical_alignment=Text.MIDDLE, text=boil('land_issues_no_information'), color=Color.GRAY, font_family='Roboto Condensed', font_size=18, font_weight=Pango.Weight.BOLD, margin=Rect([0, 0, 43, 0]), ) )
def Trainings(data): short = data['short'] vocational = data['vocational'] short_training = [ {'value': short['reached'], 'color': Color.ACCENT}, {'value': _calc_reached(short['reqd'], short['reached']), 'color': Color.GRAY}, ] vocational_training = [ {'value': vocational['reached'], 'color': Color.ACCENT}, {'value': _calc_reached(vocational['reqd'], vocational['reached']), 'color': Color.GRAY}, ] items = [ {'label': boil('training_reached'), 'color': Color.ACCENT}, {'label': boil('training_remaining'), 'color': Color.GRAY}, ] return Column( width='100%', height='100%', padding=Rect([10, 10, 4, 10]), ).add( Text( height=13, text=boil('training_sub_title'), color=Color.PRIMARY, font_family='Roboto Condensed', font_size=8, font_weight=Pango.Weight.BOLD, ), Row(width='100%', height='100% - 32', padding=Rect(4)).add( Canvas( width='50%', height='100%', renderer=PieChart( items=short_training, label=boil('training_short_training'), ) ), Canvas( width='50%', height='100%', renderer=PieChart( items=vocational_training, label=boil('training_vocational_training'), ) ), ), Row( width='100%', height=16, justify='center', align='center', ).add( *[ Label( label=item['label'], color=item['color'], ) for item in items ] ), )
def CMTable(top_data, bot_data): materials = [{ 'label': boil('status_of_cm_stone'), 'key': 'stone', 'icon': 'stone.png', 'unit': boil('status_of_cm_cubic_metre_measurement'), }, { 'label': boil('status_of_cm_aggregate'), 'key': 'aggregate', 'icon': 'aggregate.png', 'unit': boil('status_of_cm_cubic_metre_measurement'), }, { 'label': boil('status_of_cm_sand'), 'key': 'sand', 'icon': 'sand.png', 'unit': boil('status_of_cm_cubic_metre_measurement'), }, { 'label': boil('status_of_cm_timber'), 'key': 'timber', 'icon': 'timber.png', 'unit': boil('status_of_cm_cubic_feet_measurement'), }, { 'label': boil('status_of_cm_cement_(ppc)'), 'key': 'cement_ppc', 'icon': 'cement.png', 'unit': boil('status_of_cm_sack_measurement'), }, { 'label': boil('status_of_cm_cement_(opc)'), 'key': 'cement_opc', 'icon': 'cement.png', 'unit': boil('status_of_cm_sack_measurement'), }, { 'label': boil('status_of_cm_rebars'), 'key': 'rebar', 'icon': 'rebar.png', 'unit': boil('status_of_cm_kg_plural_measurement'), }, { 'label': boil('status_of_cm_tin'), 'key': 'tin', 'icon': 'tin.png', 'unit': boil('status_of_cm_bundle_measurement'), }, { 'label': boil('status_of_cm_bricks'), 'key': 'bricks', 'icon': 'bricks.png', 'unit': boil('status_of_cm_pieces_measurement'), }] rows = [] for material in materials: key = material['key'] datum = top_data[key] label = material['label'] if datum['ava'] is None: datum['ava'] = ZERO_DEFAULT rows.append([ { 'text': label, 'icon': material.get('icon') }, { 'text': material['unit'] }, { 'text': fmt_num(datum['req_quantity']) }, { 'text': datum['ava'] }, { 'text': fmt_num(datum['cost']) }, ]) headers = [ '<b>{}</b>'.format(boil(k)) for k in [ 'status_of_cm_materials_header', 'status_of_cm_unit_header', 'status_of_cm_req._quantity*_header', 'status_of_cm_ava._header', 'status_of_cm_cost_(nrs.)**_header', ] ] widths = ['28%', '12%', '25%', '10%', '25%'] return Column(width='100%', padding=Rect([16, 14, 0, 14])).add( TR_Text(widths=widths, items=headers), *[TR(widths=widths, items=row) for row in rows], BottomBox(bot_data), )
def Typologies(data): widths = ['60%', '20%', '20%'] headers = [ boil('typologies_typology'), boil('typologies_municipal'), boil('typologies_district') ] if get_lang() == 'np': row_seperator_padding = [3.5, 0, 4.5, 0] else: row_seperator_padding = [4.5, 0, 4.5, 0] # flatten and add dict # TODO: assert that we don't have duplicate keys? (exclude blanks)) rows = get_list_typo(OrderedDict((boil(k), v) for k, v in data.items()), 5) return Column( width='100%', padding=Rect(12), ).add( Row(width='100%').add(*[ Text( width=widths[i], text=header, font_family="Roboto Condensed", font_size=9, font_weight=Text.BOLD, color=Color.ACCENT, alignment=Text.LEFT if i == 0 else Text.RIGHT, ) for i, header in enumerate(headers) ]), Hr( width='100%', height=1, color=Color.PRIMARY, dash=[3], margin=Rect([3, 0, 3, 0]), ), *[ Row(width='100%').add(*[ Item( width=widths[i], text=k if i == 0 else fmt_pct( list(d_v.items())[i - 1][1], pts=2, ), index=i, padding=Rect(row_seperator_padding), ) for i in range(NUM_COLS) ]) for k, d_v in rows.items() ], *[ Row(width='100%').add(*[ Item( width=widths[i], text=' ', index=i, padding=Rect(row_seperator_padding), ) for i in range(NUM_COLS) ]) for v in range(NUM_ROWS - len(rows)) ], Text(width='100%', text=boil('typologies_cbs_footer'), font_family="Roboto Light", font_size=6, alignment=Text.RIGHT, color=Color.DARK_GRAY, padding=Rect([0, 0, 10, 0])), )
def TechnicalStaff(tech_data, mason_data): widths = ['35%', '30%', '35%'] headers = [ boil('tech_staff_staff_title'), boil('tech_staff_available_title'), boil('tech_staff_addl_req_title') ] tech_data = [[ boil(item['lookup']), fmt_num(item['available']), fmt_num(item['additional']) ] for item in tech_data] mason_data = [ boil(mason_data['lookup']), mason_data['available'], mason_data['additional'] ] # mason_data = [mason_data['label'], 100, 300] header_row = Row(width='100%').add(*[ Text( border=Border(width=0.5, color=Color.BLACK), text=item, width=widths[i], font_family='Roboto Condensed', font_size=7, font_weight=Pango.Weight.BOLD, padding=Rect(4), alignment=(Text.LEFT if i == 0 else Text.CENTER), ) for i, item in enumerate(headers) ]) # add non masons data_rows = [ Row(width='100%').add( *[ Text( border=Border(width=0.5, color=Color.BLACK), text=item, width=widths[i], height='15', font_family='Roboto Condensed', font_size=7 if i == 0 else 9, font_weight=Pango.Weight.BOLD if i == 0 else None, padding=Rect([3, 0, 0, 4]), alignment=(Text.LEFT if i == 0 else Text.CENTER), ) for i, item in enumerate(row) ], ) for row in tech_data ] # add masons data_rows.append( Row(width='100%').add(*[ Text( border=Border(width=0.5, color=Color.BLACK), text=mason_data[0], width=widths[0], font_family='Roboto Condensed', font_weight=Pango.Weight.BOLD, font_size=7, padding=Rect(4), alignment=Text.LEFT, ), Column( border=Border(width=0.5, color=Color.BLACK), height='100%', width=widths[1], ).add( Text( text='{} ({} {})'.format(fmt_num(mason_data[1][0]), fmt_num(7), boil( 'tech_staff_days')), font_family='Roboto Condensed', font_size=6, width='100%', alignment=Text.CENTER, padding=Rect([2, 0, 0, 0]), )).add( Text( text='{} ({} {})'.format(fmt_num(mason_data[1][1]), fmt_num(50), boil('tech_staff_days')), font_family='Roboto Condensed', font_size=6, width='100%', alignment=Text.CENTER, )), Column(border=Border(width=0.5, color=Color.BLACK), height='100%', width=widths[2]).add( Text( text='{} ({} {})'.format(fmt_num(mason_data[2][0]), fmt_num(7), boil('tech_staff_days')), font_family='Roboto Condensed', font_size=6, width='100%', alignment=Text.CENTER, padding=Rect([2, 0, 0, 0]), )).add( Text( text='{} ({} {})'.format( fmt_num(mason_data[2][1]), fmt_num(50), boil('tech_staff_days')), font_family='Roboto Condensed', font_size=6, width='100%', alignment=Text.CENTER, )), ])) # # Row(width=widths[1], # border=Border(width=0.5, color=Color.BLACK), # height='100%').add( # Row(border=Border(width=0.5, color=Color.BLACK)).add( # Text( # text='xx22', # font='RobotoCondensed bold 6', # font_size='RobotoCondensed bold', # alignment=Text.CENTER, # ), # ).add(Row(border=Border(width=0.5, color=Color.BLACK)).add( # Text( # text='yy', # font='RobotoCondensed 6', # ), # ), # ), return Column( width='100%', padding=Rect(16), ).add( header_row, *data_rows, )