forked from ebengoechea/de1app_plugin_SDB
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SDB.tcl
3467 lines (3138 loc) · 129 KB
/
SDB.tcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#######################################################################################################################
### A Decent DE1 app plugin to keep a synchronized SQLite database of shots and manage shots history.
#######################################################################################################################
namespace eval ::plugins::SDB {
variable author "Enrique Bengoechea"
variable contact "enri.bengoechea@gmail.com"
variable version 1.26
variable github_repo ebengoechea/de1app_plugin_SDB
variable name [translate "Shot DataBase"]
variable description [translate "Keeps your shot history in a SQLite database, and provides functions to manage shot history files."]
variable db {}
variable updating_db 0
variable db_version 5
variable sqlite_version {}
variable min_de1app_version {1.37}
variable filename_clock_format "%Y%m%dT%H%M%S"
variable friendly_clock_format "%Y/%m/%d %H:%M"
variable progress_msg {}
# DATA DICTIONARY CONVENTIONS:
# * The column name in the shot table or the lookup table must be identical to the array item key.
# * The shot_field is the variable name in the shot file, settings section. May not match the array item key in
# cases like 'other_equipment'.
# * desc_section has to be one of bean, bean_batch, equipment, extraction or people.
# * data_type has to be one of text, long_text, category, numeric or date.
variable field_lookup_whats {name name_plural short_name short_name_plural \
desc_section db_table lookup_table db_type_column1 db_type_column2 shot_field data_type \
min_value max_value n_decimals default_value small_increment big_increment
}
variable data_dictionary
array set data_dictionary {
profile_title {"Profile" "Profiles" "Profile" "Profiles" \
"" shot "" "" "" profile_title category 0 0 0}
bean_desc {"Beans" "Beans" "Beans" "Beans" \
bean V_shot "" "" "" bean_brand||bean_type category 0 0 0}
bean_brand {"Beans roaster" "Beans roasters" "Roaster" "Roasters" \
bean shot "" "" "" bean_brand category 0 0 0}
bean_type {"Beans type" "Beans types" "Name" "Names" \
bean shot "" "" "" bean_type category 0 50 0}
bean_notes {"Beans note" "Beans notes" "Note" "Notes" \
bean_batch shot "" "" "" bean_notes long_text 0 1000 0}
roast_date {"Roast date" "Roast dates" "Date" "Dates" \
bean_batch shot "" "" "" roast_date date 0 0 0}
roast_level {"Roast level" "Roast levels" "Level" "Levels" \
bean_batch shot "" "" "" roast_level category 0 50 0}
grinder_model {"Grinder name" "Grinder names" "Grinder" "Grinders" \
equipment shot "" "" "" grinder_model category 0 100 0}
grinder_setting {"Grinder setting" "Grinder settings" "Setting" "Settings" \
equipment shot "" "" "" grinder_setting category 0 100 0}
grinder_dose_weight {"Dose weight" "Dose weights" "Dose" "Doses" \
extraction shot "" "" "" grinder_dose_weight numeric 0 30 1 18 0.1 1.0}
drink_weight {"Drink weight" "Drink weights" "Weight" "Weights" \
extraction shot "" "" "" drink_weight numeric 0 500 1 36 1.0 10.0}
drink_tds {"Total Dissolved Solids" "Total Dissolved Solids %" "TDS" "TDS" \
extraction shot "" "" "" drink_tds numeric 0 25 2 8 0.01 0.1}
drink_ey {"Extraction Yield" "Extraction Yields %" "EY" "EYs" \
extraction shot "" "" "" drink_ey numeric 0 30 2 20 0.1 1.0}
espresso_enjoyment {"Enjoyment (0-100)" "Enjoyments" "Enjoyment" "Enjoyment" \
extraction shot "" "" "" espresso_enjoyment numeric 0 100 0 50 1 10}
espresso_notes {"Espresso note" "Espresso notes" "Notes" "Notes" \
extraction shot "" "" "" espresso_notes long_text 0 1000 0}
my_name {"Barista" "Baristas" "Barista" "Baristas" \
people shot "" "" "" my_name category 0 100 0 people}
drinker_name {"Drinker" "Drinkers" "Drinker" "Drinkers" \
people shot "" "" "" drinker_name category 0 100 0}
skin {"Skin" "Skins" "Skin" "Skins" \
"" shot "" "" "" skin category 0 0 0}
beverage_type {"Beverage type" "Beverage types" "Bev type" "Bev types" \
"" shot "" "" "" beverage_type category 0 0 0}
repository_links {"Repository link" "Repository links" "Repo link" "Repo links" \
"" "" "" "" "" repository_links "array" 0 0 0}
workflow {"Workflow" "Workflows" "Workflow" "Workflows" \
"" shot "" "" "" DSx2_workflow category 0 50 0}
}
namespace export string2sql strings2sql get_shot_file_path load_shot modify_shot_file \
get_db db_close persist_shot update_shot_description \
available_categories shots_using_category update_category previous_values \
has_shot_series_data field_lookup field_names
}
proc ::plugins::SDB::main {} {
variable settings
package require sqlite3
check_versions
msg -INFO "Starting the 'Shots DataBase' plugin"
if { ![info exists ::debugging] } { set ::debugging 0 }
init_sdb_metadata
set is_created [create]
trace add execution app_exit {enter} { ::plugins::SDB::db_close }
if { $is_created || $settings(sync_on_startup) } {
populate
}
# Ensure the last shot is persisted to the database whenever it is saved to history.
# We don't use 'register_state_change_handler' as that would not update the shot file if its metadata is
# changed in the Godshots page in Insight or DSx (though currently that does not work)
#register_state_change_handler Espresso Idle ::plugins::SDB::save_espresso_to_history_hook
if { [plugins enabled visualizer_upload] } {
plugins load visualizer_upload
trace add execution ::plugins::visualizer_upload::uploadShotData leave ::plugins::SDB::save_espresso_to_history_hook
} else {
# trace add execution ::save_this_espresso_to_history leave ::plugins::SDB::save_espresso_to_history_hook
::de1::event::listener::after_flow_complete_add \
[lambda {event_dict} {
::plugins::SDB::save_espresso_to_history_hook \
[dict get $event_dict previous_state] \
[dict get $event_dict this_state] \
} ]
}
}
# Paint settings screen
proc ::plugins::SDB::preload {} {
variable data
package require de1_dui 1.0
package require de1_logging 1.0
check_settings
plugins save_settings SDB
dui page add SDB_settings -namespace true -theme default -type fpdialog
return SDB_settings
}
proc ::plugins::SDB::check_settings {} {
variable settings
variable version
if {[info exists settings(db_path)] == 0 } {
set settings(db_path) "[plugin_directory]/SDB/shots.db"
} elseif { ! [file exists "[homedir]/$settings(db_path)"] } {
set settings(db_path) "[plugin_directory]/SDB/shots.db"
}
if { ![info exists settings(version)] || [package vcompare $settings(version) $version] < 0 } {
upgrade_plugin [value_or_default settings(version) ""]
}
set settings(version) $::plugins::SDB::version
set settings(db_version) $::plugins::SDB::db_version
ifexists settings(backup_modified_shot_files) 0
ifexists settings(db_persist_desc) 1
ifexists settings(db_persist_series) 0
ifexists settings(sync_on_startup) 0
ifexists settings(log_sql_statements) 0
ifexists settings(github_latest_url) "https://api.github.com/repos/ebengoechea/de1app_plugin_SDB/releases/latest"
if { ![info exists settings(last_sync_clock)] } {
set settings(last_sync_clock) 0
foreach fn "analyzed inserted modified archived unarchived removed unremoved errors" {
set settings(last_sync_$fn) 0
}
}
if { ![info exists ::settings(repository_links)] } {
set ::settings(repository_links) {}
}
}
proc ::plugins::SDB::upgrade_plugin { previous_version } {
variable settings
variable version
msg -INFO "plugin upgraded from v$previous_version to v$version"
if { $previous_version eq "" } {
set old_db_file "[homedir]/skins/DSx/DSx_User_Set/shots.db"
set new_db_file [db_path]
if { [file exists $old_db_file] && ![file exists $new_db_file]} {
file rename -force $old_db_file $new_db_file
msg -INFO "shots database file moved from old DSx DYE plugin"
}
set old_settings_file "[homedir]/skins/DSx/DSx_User_Set/DYE_settings.tdb"
if { [file exists $old_settings_file] } {
set settings_file_contents [encoding convertfrom utf-8 [read_binary_file $old_settings_file]]
if {[string length $settings_file_contents] != 0} {
array set old_settings $settings_file_contents
foreach s {backup_modified_shot_files db_persist_desc db_persist_series sync_on_startup
log_sql_statements last_sync_clock last_sync_analyzed last_sync_inserted last_sync_modified
last_sync_archived last_sync_unarchived last_sync_removed last_sync_unremoved} {
if { [info exists old_settings($s)] } {
set settings($s) $old_settings($s)
}
}
msg -INFO "settings copied from old DSx DYE plugin"
}
}
}
}
# Verify the minimum required versions of DE1 app is used, otherwise prevents startup.
proc ::plugins::SDB::check_versions {} {
variable version
if { [package vcompare [package version de1app] $::plugins::SDB::min_de1app_version] < 0 } {
message_page "[translate {Plugin 'Shot DataBase'}] v$version [translate requires] \
DE1app v$::plugins::SDB::min_de1app_version [translate {or higher}]\r\r[translate {Current DE1app version is}] [package version de1app]" \
[translate Ok]
}
}
proc ::plugins::SDB::msg { {flag ""} args } {
if { [string range $flag 0 0] eq "-" && [llength $args] > 0 } {
::logging::default_logger $flag "::plugins::SDB" {*}$args
} else {
::logging::default_logger "::plugins::SDB" $flag {*}$args
}
}
# Logs SQL statements
proc ::plugins::SDB::log_sql { sql } {
variable settings
if { $settings(log_sql_statements) } {
msg "SQL $sql"
}
}
# Embed text string in single quotes and escape any SQL character that may produce problems: duplicate single quotes.
# If text is a list, escapes and embeds each one in single quotes, and concatenates by , to be used in an "IN" sql
# statement.
proc ::plugins::SDB::strings2sql { text } {
set result [regsub -all {'} $text {''}]
set result [lmap a $result {
if {[string is integer -strict $a]} { set a } else { subst {'$a'} } }]
return [join $result ","]
}
# Escapes a string to be used within SQL
proc ::plugins::SDB::string2sql { text } {
#return "'[regsub -all {'} $text {''}]'"
return "'[string map {' ''} $text]'"
}
proc ::plugins::SDB::init_sdb_metadata {} {
metadata dictionary add sdb_table
metadata dictionary add sdb_column
metadata dictionary add sdb_lookup_table
metadata dictionary add sdb_lookup_order_by
metadata dictionary add sdb_type_column1
metadata dictionary add sdb_type_column2
foreach field [metadata fields -domain shot -category {id description}] {
metadata set $field [list sdb_table shot sdb_column $field]
}
metadata set profile_title [list sdb_table shot sdb_column profile_title]
# metadata set bean_type {sdb_type_column1 bean_brand}
# metadata set grinder_setting {sdb_type_column1 grinder_model}
metadata add drinker_name end {
domain shot
category description
section people
subsection ""
owner_type plugin
owner DYE
name "Drinker"
name_plural "Drinkers"
short_name "Drinker"
short_name_plural "Drinkers"
propagate 1
data_type category
required 0
length 1
default_dui_widget dcombobox
sdb_table shot
sdb_column drinker_name
}
metadata add repository_links end {
domain shot
category description
section id
subsection ""
owner_type plugin
owner DYE
name "Repository link"
name_plural "Repository links"
short_name "Repo link"
short_name_plural "Repo links"
propagate 0
data_type complex
required 0
length list
default_dui_widget dcombobox
}
return
metadata add bean_variety end {
domain shot
category description
section beans
subsection beans_desc
owner_type plugin
owner DYE
name "Beans variety"
name_plural "Beans varieties"
short_name "Variety"
short_name_plural "Varieties"
propagate 1
data_type category
required 0
length list
default_dui_widget dcombobox
sdb_table shot
sdb_column bean_variety
sdb_lookup_table V_variety_all
}
metadata add bean_country end {
domain shot
category description
section beans
subsection beans_desc
owner_type plugin
owner DYE
name "Beans country"
name_plural "Beans countries"
short_name "Country"
short_name_plural "Countries"
propagate 1
data_type category
required 0
length list
default_dui_widget dcombobox
sdb_table shot
sdb_column bean_country
sdb_lookup_table V_country_all
}
# sdb_lookup_order_by
metadata add bean_region end {
domain shot
category description
section beans
subsection beans_desc
owner_type plugin
owner DYE
name "Beans region"
name_plural "Beans regions"
short_name "Region"
short_name_plural "Regions"
propagate 1
data_type category
required 0
length list
default_dui_widget dcombobox
sdb_table shot
sdb_column bean_region
}
metadata add bean_altitude end {
domain shot
category description
section beans
subsection beans_desc
owner_type plugin
owner DYE
name "Beans altitude"
name_plural "Beans altitudes"
short_name "Altitude"
short_name_plural "Altitudes"
propagate 1
data_type text
required 0
length 1
default_dui_widget entry
}
metadata add bean_producer end {
domain shot
category description
section beans
subsection beans_desc
owner_type plugin
owner DYE
name "Beans producer"
name_plural "Beans producers"
short_name "Producer"
short_name_plural "Producers"
propagate 1
data_type category
required 0
length 1
default_dui_widget dcombobox
sdb_table shot
sdb_column bean_producer
}
metadata add bean_processing end {
domain shot
category description
section beans
subsection beans_desc
owner_type plugin
owner DYE
name "Beans processing"
name_plural "Beans processings"
short_name "Processing"
short_name_plural "Processings"
propagate 1
data_type category
required 0
length 1
default_dui_widget dcombobox
sdb_table shot
sdb_column bean_processing
sdb_lookup_table V_processing_all
}
metadata add bean_harvest roast_level {
domain shot
category description
section beans
subsection beans_batch
owner_type plugin
owner DYE
name "Beans harvest"
name_plural "Beans harvests"
short_name "Harvest"
short_name_plural "Harvests"
propagate 1
data_type text
required 0
length 1
default_dui_widget entry
sdb_table shot
sdb_column bean_harvest
}
metadata add bean_price bean_harvest {
domain shot
category description
section beans
subsection beans_batch
owner_type plugin
owner DYE
name "Beans price"
name_plural "Beans prices"
short_name "Price"
short_name_plural "Prices"
propagate 1
data_type number
min 0.0
max 1000000.0
default 10.0
smallincrement 0.10
bigincrement 1.0
n_decimals 2
measure_unit ""
required 0
length 1
default_dui_widget dclicker
sdb_table shot
sdb_column bean_price
}
metadata add bean_quality_score bean_price {
domain shot
category description
section beans
subsection beans_batch
owner_type plugin
owner DYE
name "Quality score"
name_plural "Quality score"
short_name "Quality"
short_name_plural "Qualities"
propagate 1
data_type number
min 0
max 100
default 85
smallincrement 1
bigincrement 10
n_decimals 0
measure_unit ""
required 0
length 1
default_dui_widget dclicker
sdb_table shot
sdb_column bean_quality_score
}
metadata add bean_freeze_date bean_quality_score {
domain shot
category description
section beans
subsection beans_batch
owner_type plugin
owner DYE
name "Freeze date"
name_plural "Freeze dates"
short_name "Frozen at"
short_name_plural "Frozen at"
propagate 1
data_type date
required 0
length 1
default_dui_widget entry
sdb_table shot
sdb_column bean_freeze_date
}
metadata add bean_unfreeze_date bean_freeze_date {
domain shot
category description
section beans
subsection beans_batch
owner_type plugin
owner DYE
name "Unfreeze date"
name_plural "Unfreeze dates"
short_name "Unfrozen at"
short_name_plural "Unfrozen at"
propagate 1
data_type date
required 0
length 1
default_dui_widget entry
sdb_table shot
sdb_column bean_unfreeze_date
}
metadata add bean_open_date bean_unfreeze_date {
domain shot
category description
section beans
subsection beans_batch
owner_type plugin
owner DYE
name "Open date"
name_plural "Open dates"
short_name "Open at"
short_name_plural "Open at"
propagate 1
data_type date
required 0
length 1
default_dui_widget entry
sdb_table shot
sdb_column bean_open_date
}
metadata add grinder_burrs end {
domain shot
category description
section equipment
subsection grinder
owner_type plugin
owner DYE
name "Grinder burrs"
name_plural "Grinder burrs"
short_name "Burrs"
short_name_plural "Burrs"
propagate 1
data_type category
required 0
length 1
default_dui_widget dcombobox
sdb_table shot
sdb_column grinder_burrs
}
metadata add grinder_rpm end {
domain shot
category description
section equipment
subsection grinder
owner_type plugin
owner DYE
name "Grinder RPM"
name_plural "Grinder RPM"
short_name "RPM"
short_name_plural "RPM"
propagate 1
data_type category
required 0
length 1
default_dui_widget dcombobox
sdb_table shot
sdb_column grinder_rpm
}
metadata add portafilter_model end {
domain shot
category description
section equipment
subsection ""
owner_type plugin
owner DYE
name "Portafilter"
name_plural "Portafilters"
short_name "PF"
short_name_plural "PFs"
propagate 1
data_type category
required 0
length 1
default_dui_widget dcombobox
sdb_table shot
sdb_column portafilter
}
metadata add portafilter_basket end {
domain shot
category description
section equipment
subsection ""
owner_type plugin
owner DYE
name "Portafilter basket"
name_plural "Portafilter baskets"
short_name "Basket"
short_name_plural "Baskets"
propagate 1
data_type category
required 0
length 1
default_dui_widget dcombobox
sdb_table shot
sdb_column portafilter_basket
}
metadata add filter_top end {
domain shot
category description
section equipment
subsection ""
owner_type plugin
owner DYE
name "Top filter"
name_plural "Top filters"
short_name "Top filter"
short_name_plural "Top filters"
propagate 1
data_type category
required 0
length 1
default_dui_widget dcombobox
sdb_table shot
sdb_column filter_top
}
metadata add filter_bottom end {
domain shot
category description
section equipment
subsection ""
owner_type plugin
owner DYE
name "Bottom filter"
name_plural "Bottom filters"
short_name "Bot. filter"
short_name_plural "Bot. filters"
propagate 1
data_type category
required 0
length 1
default_dui_widget dcombobox
sdb_table shot
sdb_column filter_bottom
}
metadata add distribution_tool end {
domain shot
category description
section equipment
subsection ""
owner_type plugin
owner DYE
name "Distribution tool"
name_plural "Distribution tools"
short_name "Dist. tool"
short_name_plural "Dist. tools"
propagate 1
data_type category
required 0
length 1
default_dui_widget dcombobox
sdb_table shot
sdb_column distribution_tool
}
metadata add distribution_technique end {
domain shot
category description
section equipment
subsection ""
owner_type plugin
owner DYE
name "Distrib. technique"
name_plural "Distrib. techniques"
short_name "Dist. tech."
short_name_plural "Dist. techs."
propagate 1
data_type category
required 0
length 1
default_dui_widget dcombobox
sdb_table shot
sdb_column distribution_technique
}
metadata add tamper end {
domain shot
category description
section equipment
subsection ""
owner_type plugin
owner DYE
name "Tamper"
name_plural "Tampers"
short_name "Tamper"
short_name_plural "Tampers"
propagate 1
data_type category
required 0
length 1
default_dui_widget dcombobox
sdb_table shot
sdb_column tamper
}
metadata add tamping_technique end {
domain shot
category description
section equipment
subsection ""
owner_type plugin
owner DYE
name "Tamping technique"
name_plural "Tamping techniques"
short_name "Tamp tech."
short_name_plural "Tamp techs."
propagate 1
data_type category
required 0
length 1
default_dui_widget dcombobox
sdb_table shot
sdb_column tamping_technique
}
metadata add calc_ey_from_tds drink_weight {
domain shot
category description
section extraction
subsection drink
owner_type plugin
owner DYE
name "Calculate EY from TDS"
name_plural "Calculate EYs from TDS"
short_name "Calc. EY"
short_name_plural "Calc. EYs"
propagate 0
data_type boolean
default 1
required 1
length 1
default_dui_widget dcheckbox
sdb_table shot
sdb_column calc_ey_from_tds
}
metadata add drink_brix drink_tds {
domain shot
category description
section extraction
subsection drink
owner_type plugin
owner DYE
name "Brix"
name_plural "Brix"
short_name "Brix"
short_name_plural "Brix"
propagate 0
data_type number
min 0.0
max 25.0
default 8.0
smallincrement 0.01
bigincrement 0.1
n_decimals 2
measure_unit %
required 0
length 1
default_dui_widget dclicker
sdb_table shot
sdb_column drink_brix
}
metadata add refractometer_model end {
domain shot
category description
section equipment
subsection ""
owner_type plugin
owner DYE
name "Refractometer model"
name_plural "Refractometer models"
short_name "Refractometer"
short_name_plural "Refractometers"
propagate 1
data_type category
required 0
length 1
default_dui_widget dcombobox
sdb_table shot
sdb_column refractometer_model
}
metadata add refractometer_temp drink_brix {
domain shot
category description
section extraction
subsection drink
owner_type plugin
owner DYE
name "Refract. temperature"
name_plural "Refract. temperatures"
short_name "Refr. temp."
short_name_plural "Refr. temps."
propagate 0
data_type number
min 10.0
max 80.0
default 24.0
smallincrement 0.1
bigincrement 5
n_decimals 1
measure_unit "ºC"
required 0
length 1
default_dui_widget dclicker
sdb_table shot
sdb_column refractometer_temp
}
metadata add refractometer_technique refractometer_temp {
domain shot
category description
section extraction
subsection drink
owner_type plugin
owner DYE
name "Refract. technique"
name_plural "Refract. techniques"
short_name "Refr. tech."
short_name_plural "Refr. techs."
propagate 1
data_type category
required 0
length 1
default_dui_widget dcombobox
sdb_table shot
sdb_column refractometer_technique
}
metadata add final_beverage_type end {
domain shot
category description
section beverage
subsection ""
owner_type plugin
owner DYE
name "Beverage type"
name_plural "Beverage types"
short_name "Beverage"
short_name_plural "Beverage"
propagate 1
data_type category
required 0
length 1
default_dui_widget dcombobox
sdb_table shot
sdb_column final_beverage_type
}
metadata add bev_added_liquid_type end {
domain shot
category description
section beverage
subsection ""
owner_type plugin
owner DYE
name "Added liquid"
name_plural "Added liquids"
short_name "Liquid"
short_name_plural "Liquids"
propagate 1
data_type category
required 0
length 1
default_dui_widget dcombobox
sdb_table shot
sdb_column bev_added_liquid_type
}
metadata add bev_added_liquid_weight end {
domain shot
category description
section beverage
subsection ""
owner_type plugin
owner DYE
name "Added liquid weight"
name_plural "Added liquid weights"
short_name "Liquid weight"
short_name_plural "Liquid weights"
propagate 1
data_type number
min 0.0
max 500.0
default 50.0
smallincrement 1.0
bigincrement 10.0
n_decimals 1
measure_unit g
required 0
length 1
default_dui_widget dclicker
sdb_table shot
sdb_column bev_added_liquid_weight
}
metadata add bev_added_liquid_temp end {
domain shot
category description
section beverage
subsection ""
owner_type plugin
owner DYE
name "Added liquid temperature"
name_plural "Added liquid temperatures"
short_name "Liquid temp."
short_name_plural "Liquid temps."
propagate 1
data_type number
min 0.0
max 100.0
default 50.0
smallincrement 1.0
bigincrement 10.0
n_decimals 1
measure_unit "ºC"
required 0
length 1
default_dui_widget dclicker
sdb_table shot
sdb_column bev_added_liquid_temp
}
# foreach field {bean_country bean_region bean_variety bean_processing} {
# metadata set $field [list sdb_lookup_table [string range $field 5 end]]
# }
}
# Looks up fields metadata in the data dictionary. 'what' can be a list with multiple items, then a list is returned.
proc ::plugins::SDB::field_lookup { field {what name} } {
variable data_dictionary
variable field_lookup_whats
if { $field eq "" } return
if { ![info exists data_dictionary($field)] } {
#msg "WARNING data field '$field' unmatched in proc field_lookup"
return {}
}
set result {}
foreach whatpart $what {
set match_idx [lsearch -all $field_lookup_whats $whatpart]
if { $match_idx == -1 } {
msg "WARNING what item '$whatpart' unmatched in proc field_lookup"
lappend result {}
} else {
lappend result [lindex $data_dictionary($field) $match_idx]
}
}
if { [llength $result] == 1 } { set result [lindex $result 0] }
return $result
}
proc ::plugins::SDB::field_names { {data_types {} } {db_tables {}} {desc_sections {}} } {
variable data_dictionary
variable field_lookup_whats
if { $data_types eq "" && $db_tables eq "" && $desc_sections eq "" } {
return [array names data_dictionary]
}
if { $data_types eq "" } {
set dt_idx -1
} else {
set dt_idx [lsearch -all $field_lookup_whats "data_type"]
}
if { $db_tables eq "" } {
set tab_idx -1
} else {
set tab_idx [lsearch -all $field_lookup_whats "db_table"]
}
if { $desc_sections eq "" } {
set desc_idx -1
} else {
set desc_idx [lsearch -all $field_lookup_whats "desc_section"]
}
set fields {}
foreach fn [array names data_dictionary] {
set data_type [lindex $data_dictionary($fn) $dt_idx]
set db_table [lindex $data_dictionary($fn) $tab_idx]
set desc_section [lindex $data_dictionary($fn) $desc_idx]