5
5
import json
6
6
import typing
7
7
import jinja2
8
+ import urllib
9
+ import zlib
10
+ import base64
8
11
import numpy as np
9
12
10
13
from .. import markdown_tools
11
14
12
15
from caimira .calculator .models import models
13
16
from caimira .calculator .validators .virus .virus_validator import VirusFormData
14
- from caimira .calculator .report .virus_report_data import calculate_report_data , interesting_times , manufacture_alternative_scenarios , manufacture_viral_load_scenarios_percentiles , comparison_report , generate_permalink
17
+ from caimira .calculator .report .virus_report_data import alternative_scenarios_data , calculate_report_data , calculate_vl_scenarios_percentiles
15
18
16
19
17
20
def minutes_to_time (minutes : int ) -> str :
@@ -62,6 +65,25 @@ def non_zero_percentage(percentage: int) -> str:
62
65
return "{:0.1f}%" .format (percentage )
63
66
64
67
68
+ def generate_permalink (base_url , get_root_url , get_root_calculator_url , form : VirusFormData ):
69
+ form_dict = VirusFormData .to_dict (form , strip_defaults = True )
70
+
71
+ # Generate the calculator URL arguments that would be needed to re-create this
72
+ # form.
73
+ args = urllib .parse .urlencode (form_dict )
74
+
75
+ # Then zlib compress + base64 encode the string. To be inverted by the
76
+ # /_c/ endpoint.
77
+ compressed_args = base64 .b64encode (zlib .compress (args .encode ())).decode ()
78
+ qr_url = f"{ base_url } { get_root_url ()} /_c/{ compressed_args } "
79
+ url = f"{ base_url } { get_root_calculator_url ()} ?{ args } "
80
+
81
+ return {
82
+ 'link' : url ,
83
+ 'shortened' : qr_url ,
84
+ }
85
+
86
+
65
87
@dataclasses .dataclass
66
88
class VirusReportGenerator :
67
89
jinja_loader : jinja2 .BaseLoader
@@ -74,44 +96,53 @@ def build_report(
74
96
form : VirusFormData ,
75
97
executor_factory : typing .Callable [[], concurrent .futures .Executor ],
76
98
) -> str :
77
- model = form .build_model ()
78
99
context = self .prepare_context (
79
- base_url , model , form , executor_factory = executor_factory )
100
+ base_url , form , executor_factory = executor_factory )
80
101
return self .render (context )
81
102
82
103
def prepare_context (
83
104
self ,
84
105
base_url : str ,
85
- model : models .ExposureModel ,
86
106
form : VirusFormData ,
87
107
executor_factory : typing .Callable [[], concurrent .futures .Executor ],
88
108
) -> dict :
89
109
now = datetime .utcnow ().astimezone ()
90
110
time = now .strftime ("%Y-%m-%d %H:%M:%S UTC" )
91
111
92
- data_registry_version = f"v{ model .data_registry .version } " if model .data_registry .version else None
93
112
context = {
94
- 'model' : model ,
95
113
'form' : form ,
96
114
'creation_date' : time ,
97
- 'data_registry_version' : data_registry_version ,
98
115
}
99
116
100
- scenario_sample_times = interesting_times (model )
101
- report_data = calculate_report_data (
102
- form , model , executor_factory = executor_factory )
117
+ # Main report data
118
+ report_data = calculate_report_data (form , executor_factory )
103
119
context .update (report_data )
104
120
105
- alternative_scenarios = manufacture_alternative_scenarios (form )
106
- context ['alternative_viral_load' ] = manufacture_viral_load_scenarios_percentiles (
107
- model ) if form .conditional_probability_viral_loads else None
108
- context ['alternative_scenarios' ] = comparison_report (
109
- form , report_data , alternative_scenarios , scenario_sample_times , executor_factory = executor_factory ,
110
- )
111
- context ['permalink' ] = generate_permalink (
121
+ # Model and Data Registry
122
+ model : models .ExposureModel = report_data ['model' ]
123
+ data_registry_version : typing .Optional [str ] = f"v{ model .data_registry .version } " if model .data_registry .version else None
124
+
125
+ # Alternative scenarios data
126
+ alternative_scenarios : typing .Dict [str ,typing .Any ] = alternative_scenarios_data (form , report_data , executor_factory )
127
+ context .update (alternative_scenarios )
128
+
129
+ # Alternative viral load data
130
+ if form .conditional_probability_viral_loads :
131
+ alternative_viral_load : typing .Dict [str ,typing .Any ] = calculate_vl_scenarios_percentiles (model )
132
+ context .update (alternative_viral_load )
133
+
134
+ # Permalink
135
+ permalink : typing .Dict [str , str ] = generate_permalink (
112
136
base_url , self .get_root_url , self .get_root_calculator_url , form )
113
- context ['get_url' ] = self .get_root_url
114
- context ['get_calculator_url' ] = self .get_root_calculator_url
137
+
138
+ # URLs (root, calculator and permalink)
139
+ context .update ({
140
+ 'model_repr' : repr (model ),
141
+ 'data_registry_version' : data_registry_version ,
142
+ 'permalink' : permalink ,
143
+ 'get_url' : self .get_root_url ,
144
+ 'get_calculator_url' : self .get_root_calculator_url ,
145
+ })
115
146
116
147
return context
117
148
0 commit comments