1
+ import 'package:davi/davi.dart' ;
1
2
import 'package:flutter/material.dart' ;
3
+ import 'package:simdart/simdart.dart' ;
2
4
import 'package:simdart_demo/production_line/production_line.dart' ;
3
5
import 'package:simdart_demo/production_line/radio_button.dart' ;
4
6
import 'package:simdart_demo/production_line/result_card.dart' ;
@@ -15,12 +17,10 @@ class ProductionLineExample extends StatefulWidget {
15
17
16
18
class ProductionLineExampleState extends State <ProductionLineExample > {
17
19
bool loading = false ;
18
- int duration = 0 ;
19
-
20
20
21
21
ValueNotifier <int > packers = ValueNotifier (5 );
22
22
ValueNotifier <int > assemblers = ValueNotifier (3 );
23
- ValueNotifier <int > inspectors= ValueNotifier (2 );
23
+ ValueNotifier <int > inspectors = ValueNotifier (2 );
24
24
ValueNotifier <int > requestedItemCount = ValueNotifier (20 );
25
25
ValueNotifier <int > requestInterval = ValueNotifier (1 );
26
26
ValueNotifier <int > assemblyDuration = ValueNotifier (5 );
@@ -33,26 +33,43 @@ class ProductionLineExampleState extends State<ProductionLineExample> {
33
33
34
34
@override
35
35
Widget build (BuildContext context) {
36
+ TextStyle titleStyle = TextStyle (fontWeight: FontWeight .bold);
36
37
List <Widget > children = [
38
+ Text ("Simulation setup" , style: titleStyle),
37
39
_buildForm (context),
38
- ElevatedButton (
39
- onPressed: ! loading ? _run : null , child: Text ('Run: $ duration ' ))
40
+ TextButton (
41
+ onPressed: ! loading ? _run : null , child: Text ('Run the simulation ' ))
40
42
];
41
43
if (loading) {
42
44
children.add (CircularProgressIndicator ());
43
45
} else if (simulationResult != null ) {
46
+ children.add (Text ("Simulation result" , style: titleStyle));
47
+
44
48
children.add (ResultGrid (result: simulationResult! ));
45
49
46
- children.add (Wrap (spacing: 16 ,
47
- runSpacing: 16 ,children: [SparklineResource (title: 'Assemblers usage' ,
48
- simulationResult: simulationResult! ,
49
- resourceId: 'a' ),
50
- SparklineResource (title: 'Inspectors usage' ,
50
+ children.add (Wrap (spacing: 32 , runSpacing: 16 , children: [
51
+ SparklineResource (
52
+ title: 'Assemblers usage' ,
53
+ simulationResult: simulationResult! ,
54
+ resourceId: 'a' ),
55
+ SparklineResource (
56
+ title: 'Inspectors usage' ,
51
57
simulationResult: simulationResult! ,
52
58
resourceId: 'i' ),
53
- SparklineResource (title: 'Packers usage' ,
59
+ SparklineResource (
60
+ title: 'Packers usage' ,
54
61
simulationResult: simulationResult! ,
55
- resourceId: 'p' )]));
62
+ resourceId: 'p' )
63
+ ]));
64
+
65
+ children.add (Text ("Simulation events" , style: titleStyle));
66
+
67
+ children.add (EventsViewer (
68
+ key: UniqueKey (),
69
+ tracks: simulationResult! .tracks,
70
+ assemblers: assemblers.value,
71
+ inspectors: inspectors.value,
72
+ packers: packers.value));
56
73
}
57
74
58
75
return Column (
@@ -64,13 +81,11 @@ class ProductionLineExampleState extends State<ProductionLineExample> {
64
81
Widget _buildForm (BuildContext context) {
65
82
TableBuilder tableBuilder = TableBuilder ();
66
83
67
-
68
-
69
84
tableBuilder.row ()
70
- ..add (_buildText ('Assemblers:' ))
71
- ..add (RadioButton (value: 3 , selectedValue: assemblers))
72
- ..add (RadioButton (value: 5 , selectedValue: assemblers))
73
- ..add (RadioButton (value: 7 , selectedValue: assemblers));
85
+ ..add (_buildText ('Assemblers:' ))
86
+ ..add (RadioButton (value: 3 , selectedValue: assemblers))
87
+ ..add (RadioButton (value: 5 , selectedValue: assemblers))
88
+ ..add (RadioButton (value: 7 , selectedValue: assemblers));
74
89
75
90
tableBuilder.row ()
76
91
..add (_buildText ('Inspectors:' ))
@@ -79,10 +94,10 @@ class ProductionLineExampleState extends State<ProductionLineExample> {
79
94
..add (RadioButton (value: 8 , selectedValue: inspectors));
80
95
81
96
tableBuilder.row ()
82
- ..add (_buildText ('Packers:' ))
83
- ..add (RadioButton (value: 5 , selectedValue: packers))
84
- ..add (RadioButton (value: 10 , selectedValue: packers))
85
- ..add (RadioButton (value: 15 , selectedValue: packers));
97
+ ..add (_buildText ('Packers:' ))
98
+ ..add (RadioButton (value: 5 , selectedValue: packers))
99
+ ..add (RadioButton (value: 10 , selectedValue: packers))
100
+ ..add (RadioButton (value: 15 , selectedValue: packers));
86
101
87
102
tableBuilder.row ()
88
103
..add (_buildText ('Requested items:' ))
@@ -93,8 +108,8 @@ class ProductionLineExampleState extends State<ProductionLineExample> {
93
108
tableBuilder.row ()
94
109
..add (_buildText ('Request interval (min):' ))
95
110
..add (RadioButton (value: 1 , selectedValue: requestInterval))
96
- ..add (RadioButton (value: 10 , selectedValue: requestInterval))
97
- ..add (RadioButton (value: 20 , selectedValue: requestInterval));
111
+ ..add (RadioButton (value: 5 , selectedValue: requestInterval))
112
+ ..add (RadioButton (value: 10 , selectedValue: requestInterval));
98
113
99
114
tableBuilder.row ()
100
115
..add (_buildText ('Assembly duration (min):' ))
@@ -133,9 +148,9 @@ class ProductionLineExampleState extends State<ProductionLineExample> {
133
148
});
134
149
135
150
ProductionLine productionLine = ProductionLine (
136
- assemblerCount: assemblers.value,
137
- inspectorCount: inspectors.value,
138
- packerCount: packers.value,
151
+ assemblerCount: assemblers.value,
152
+ inspectorCount: inspectors.value,
153
+ packerCount: packers.value,
139
154
inspectionDuration: inspectionDuration.value,
140
155
packagingDuration: packagingDuration.value,
141
156
assemblyDuration: assemblyDuration.value,
@@ -163,32 +178,119 @@ class ResultGrid extends StatelessWidget {
163
178
spacing: 16 ,
164
179
runSpacing: 16 ,
165
180
children: < Widget > [
166
- ResultCard (value: result.assembleCount.toString (), text: 'Assembled' ),
181
+ ResultCard (
182
+ value: result.assembleCount.toString (),
183
+ text: 'Assembled' ,
184
+ icon: Icons .build),
167
185
ResultCard (
168
186
value: result.rejectedCount.toString (),
169
187
text: 'Rejected' ,
188
+ icon: Icons .block,
170
189
textColor: Colors .red),
171
190
ResultCard (
172
191
value: result.packagedCount.toString (),
173
192
text: 'Packaged' ,
193
+ icon: Icons .inventory_2_outlined,
174
194
textColor: Colors .green),
175
195
ResultCard (
176
- value: result.duration.toString (), text: 'Total duration (min)' ),
196
+ value: result.duration.toString (),
197
+ text: 'Total duration (min)' ,
198
+ icon: Icons .schedule),
177
199
ResultCard (
178
200
value: result.assembleRate.toStringAsFixed (2 ),
179
- text: 'Assemble rate (items/min)' ),
201
+ text: 'Assemble rate (items/min)' ,
202
+ icon: Icons .trending_up),
180
203
ResultCard (
181
204
value: '${result .rejectionRate .toStringAsFixed (2 )}%' ,
182
205
text: 'Rejection rate' ,
206
+ icon: Icons .trending_up,
183
207
textColor: Colors .red),
184
208
ResultCard (
185
209
value: result.packagingRate.toStringAsFixed (2 ),
186
210
text: 'Packaging rate (items/min)' ,
211
+ icon: Icons .trending_up,
187
212
textColor: Colors .green),
188
213
ResultCard (
189
214
value: result.averageProductionDuration.toStringAsFixed (2 ),
190
- text: 'Avg. production duration (min/item)' ),
215
+ text: 'Avg. production duration (min/item)' ,
216
+ icon: Icons .trending_up),
191
217
],
192
218
);
193
219
}
194
220
}
221
+
222
+ class EventsViewer extends StatelessWidget {
223
+ const EventsViewer (
224
+ {super .key,
225
+ required this .tracks,
226
+ required this .packers,
227
+ required this .assemblers,
228
+ required this .inspectors});
229
+
230
+ final List <SimulationTrack > tracks;
231
+ final int packers;
232
+ final int assemblers;
233
+ final int inspectors;
234
+
235
+ @override
236
+ Widget build (BuildContext context) {
237
+ return SizedBox (height: 300 , child: _table ());
238
+ }
239
+
240
+ Widget _table () {
241
+ DaviModel <SimulationTrack > model = DaviModel (
242
+ rows: tracks,
243
+ columns: [
244
+ DaviColumn (
245
+ name: 'Time (min)' , cellValue: (params) => params.data.time),
246
+ DaviColumn (
247
+ name: 'Status' ,
248
+ cellValue: (params) => params.data.status,
249
+ cellTextStyle: (params) => params.data.status == Status .rejected
250
+ ? TextStyle (color: Colors .red)
251
+ : null ),
252
+ DaviColumn (name: 'Name' , cellValue: (params) => params.data.name),
253
+ DaviColumn (
254
+ cellPadding: EdgeInsets .all (4 ),
255
+ name: 'Assemblers' ,
256
+ cellBarValue: (params) =>
257
+ params.data.resourceUsage['a' ]! / assemblers,
258
+ cellBarStyle: CellBarStyle (
259
+ barBackground: Colors .transparent,
260
+ barForeground: (value) {
261
+ return Color .lerp (
262
+ Colors .green[200 ], Colors .red[200 ], value)! ;
263
+ }),
264
+ cellBarValueStringify: (params) =>
265
+ '${params .data .resourceUsage ['a' ]!}/$assemblers ' ),
266
+ DaviColumn (
267
+ cellPadding: EdgeInsets .all (4 ),
268
+ name: 'Inspectors' ,
269
+ cellBarValue: (params) =>
270
+ params.data.resourceUsage['i' ]! / inspectors,
271
+ cellBarStyle: CellBarStyle (
272
+ barBackground: Colors .transparent,
273
+ barForeground: (value) {
274
+ return Color .lerp (
275
+ Colors .green[200 ], Colors .red[200 ], value)! ;
276
+ }),
277
+ cellBarValueStringify: (params) =>
278
+ '${params .data .resourceUsage ['i' ]!}/$inspectors ' ),
279
+ DaviColumn (
280
+ cellPadding: EdgeInsets .all (4 ),
281
+ name: 'Packers' ,
282
+ cellBarValue: (params) =>
283
+ params.data.resourceUsage['p' ]! / packers,
284
+ cellBarStyle: CellBarStyle (
285
+ barBackground: Colors .transparent,
286
+ barForeground: (value) {
287
+ return Color .lerp (
288
+ Colors .green[200 ], Colors .red[200 ], value)! ;
289
+ }),
290
+ cellBarValueStringify: (params) =>
291
+ '${params .data .resourceUsage ['p' ]!}/$packers ' )
292
+ ],
293
+ sortingMode: SortingMode .disabled);
294
+ return Davi (model, columnWidthBehavior: ColumnWidthBehavior .fit);
295
+ }
296
+ }
0 commit comments