File size: 42,783 Bytes
2737675
436a2c0
2737675
436a2c0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cfca93e
 
436a2c0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2737675
93a28dc
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
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
<!DOCTYPE html>
<html lang="zh-TW">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>營養液反向計算機</title>
    <style>
        .container {
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }
        .fertilizer-list {
            margin-top: 20px;
            border: 1px solid #e0e0e0;
            padding: 20px;
            border-radius: 12px;
            background-color: #ffffff;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
        }
        .fertilizer-list h2 {
            margin-top: 0;
            color: #2c3e50;
            border-bottom: 2px solid #eef2f7;
            padding-bottom: 12px;
            margin-bottom: 20px;
            font-size: 1.4em;
        }
        .fertilizer-list ul {
            list-style: none;
            padding: 0;
            margin: 0;
        }
        .fertilizer-list li {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 12px 16px;
            margin-bottom: 10px;
            background-color: #f8fafc;
            border: 1px solid #edf2f7;
            border-radius: 8px;
            transition: all 0.2s ease;
        }
        .fertilizer-list li:hover {
            background-color: #edf2f7;
            transform: translateX(2px);
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
        }
        .fertilizer-list .fertilizer-info {
            flex-grow: 1;
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding-right: 24px;
            min-width: 0;
            gap: 16px;
        }
        .fertilizer-list .formula {
            font-weight: 500;
            color: #2d3748;
            flex: 1;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            font-size: 0.95em;
        }
        .fertilizer-list .amount {
            display: flex;
            align-items: center;
            gap: 8px;
            min-width: 120px;
            justify-content: flex-end;
        }
        .fertilizer-list .amount-display {
            cursor: pointer;
            padding: 4px 8px;
            border-radius: 4px;
            background-color: #edf2f7;
            color: #4a5568;
            font-family: monospace;
            transition: all 0.2s ease;
        }
        .fertilizer-list .amount-display:hover {
            background-color: #e2e8f0;
        }
        .fertilizer-list .amount-input {
            width: 100px;
            padding: 4px 8px;
            border: 1px solid #cbd5e0;
            border-radius: 4px;
            text-align: right;
            font-family: monospace;
        }
        .fertilizer-list .edit-controls {
            display: flex;
            gap: 4px;
        }
        .fertilizer-list .edit-btn {
            padding: 4px 8px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
            transition: all 0.2s ease;
        }
        .fertilizer-list .save-btn {
            background-color: #48bb78;
            color: white;
        }
        .fertilizer-list .save-btn:hover {
            background-color: #38a169;
        }
        .fertilizer-list .cancel-btn {
            background-color: #a0aec0;
            color: white;
        }
        .fertilizer-list .cancel-btn:hover {
            background-color: #718096;
        }
        .fertilizer-list .remove-btn {
            background-color: #fc8181;
            color: white;
            border: none;
            padding: 6px 12px;
            border-radius: 6px;
            cursor: pointer;
            transition: all 0.2s ease;
            font-size: 0.9em;
        }
        .fertilizer-list .remove-btn:hover {
            background-color: #f56565;
        }
        .no-fertilizers {
            text-align: center;
            color: #718096;
            font-style: italic;
            padding: 24px;
            background-color: #f7fafc;
            border-radius: 8px;
            border: 1px dashed #cbd5e0;
        }
        .result-table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 20px;
        }
        .result-table th, .result-table td {
            border: 1px solid #ccc;
            padding: 8px;
            text-align: center;
        }
        .fertilizer-selector select {
            width: 100%;
            margin: 10px 0;
            max-height: 200px;
        }
        
        #fertilizer-search {
            width: 100%;
            padding: 8px;
            margin-bottom: 5px;
            border: 1px solid #ccc;
            border-radius: 4px;
        }
        .test-btn {
            background-color: #3498db;
            color: white;
            border: none;
            padding: 8px 15px;
            border-radius: 4px;
            cursor: pointer;
            margin-bottom: 10px;
            transition: background-color 0.2s;
        }
        .test-btn:hover {
            background-color: #2980b9;
        }
        
        /* 新增的樣式 */
        .target-input {
            width: 80px;
            padding: 4px 8px;
            border: 1px solid #cbd5e0;
            border-radius: 4px;
            text-align: right;
            font-family: monospace;
        }
        .target-row td {
            padding: 8px;
            vertical-align: middle;
        }
        /* 添加導航按鈕樣式 */
        .nav-button {
            display: inline-block;
            padding: 8px 16px;
            background-color: #4299e1;
            color: white;
            text-decoration: none;
            border-radius: 6px;
            transition: all 0.2s ease;
            margin-bottom: 20px;
        }

        .nav-button:hover {
            background-color: #3182ce;
            transform: translateY(-1px);
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        }

        .input-mode-switch {
            display: flex;
            gap: 10px;
            margin-bottom: 15px;
            justify-content: flex-end;
        }

        .mode-btn {
            padding: 6px 12px;
            border: 1px solid #4299e1;
            background-color: white;
            color: #4299e1;
            border-radius: 4px;
            cursor: pointer;
            transition: all 0.2s ease;
        }

        .mode-btn.active {
            background-color: #4299e1;
            color: white;
        }

        .target-input[disabled] {
            background-color: #f7fafc;
            cursor: not-allowed;
        }

        .control-panel {
            margin: 20px 0;
            text-align: center;
        }

        .calculate-btn {
            background-color: #48bb78;
            color: white;
            border: none;
            padding: 12px 24px;
            border-radius: 6px;
            cursor: pointer;
            font-size: 1.1em;
            transition: all 0.2s ease;
        }

        .calculate-btn:hover {
            background-color: #38a169;
            transform: translateY(-1px);
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>營養液反向計算機</h1>
        
        <a href="index.html" class="nav-button">
            ← 返回成分計算機
        </a>

        <!-- 目標養分輸入區域 -->
        <div class="fertilizer-list">
            <h2>目標養分含量</h2>
            <div class="input-mode-switch">
                <button class="mode-btn active" data-mode="ppm">ppm 模式</button>
                <button class="mode-btn" data-mode="meq">meq/L 模式</button>
            </div>
            <table class="result-table">
                <thead>
                    <tr>
                        <th>元素</th>
                        <th>目標 ppm</th>
                        <th>目標 meq/L</th>
                        <th>目標 mmol/L</th>
                    </tr>
                </thead>
                <tbody id="target-nutrients">
                    <!-- 將由 JavaScript 動態填充 -->
                </tbody>
            </table>
            <div class="control-panel">
                <button onclick="calculateFertilizerAmounts()" class="calculate-btn">
                    計算肥料用量
                </button>
            </div>
        </div>

        <!-- 可用肥料清單 -->
        <div class="fertilizer-list">
            <h2>可用肥料</h2>
            <div id="available-fertilizers">
                <!-- 由 JavaScript 生成 -->
            </div>
        </div>
    </div>

    <script>
        // 添加名稱對應表
        const fertilizerAliases = {
            'Fe-EDTA·3H2O': 'C10H12FeN2NaO8·3H2O',
            '螯合鐵': 'C10H12FeN2NaO8·3H2O'
        };

        // 分子量對照表
        const molecularWeights = {
            // 化合物
            'Ca(NO3)2·4H2O': 236.149920,    // 40.078 + 2(14.0067 + 3*15.999) + 4(18.015340)
            'KNO3': 101.102530,             // 39.0983 + 14.0067 + 3*15.999
            'MgSO4·7H2O': 246.474780,       // 24.305 + 32.065 + 4*15.999 + 7(18.015340)
            'NH4H2PO4': 115.025738,         // 14.0067 + 4*1.007940 + 30.973762 + 4*15.999
            'Ca(H2PO4)2·H2O': 252.082802,   // 40.078 + 2(2*1.007940 + 30.973762 + 4*15.999) + 18.015340
            'C10H12FeN2NaO8·3H2O': 412.147420,  // Fe-EDTA·3H2O: 10*12.0107 + 12*1.007940 + 55.845 + 2*14.0067 + 22.989770 + 8*15.999 + 3(18.015340)
            'H3BO3': 61.833220,             // 3*1.007940 + 10.811 + 3*15.999
            'MnCl2·4H2O': 197.905360,       // 54.938045 + 2*35.453 + 4(18.015340)
            'ZnSO4·7H2O': 287.539780,       // 65.38 + 32.065 + 4*15.999 + 7(18.015340)
            'CuSO4·5H2O': 249.685700,       // 63.546 + 32.065 + 4*15.999 + 5(18.015340)
            'Na2MoO4·2H2O': 241.950680,     // 2*22.989770 + 95.96 + 4*15.999 + 2(18.015340)
            'KH2PO4': 136.085838,           // 39.0983 + 2*1.007940 + 30.973762 + 4*15.999
            'Ca(NO3)2': 164.088400,         // 40.078 + 2(14.0067 + 3*15.999)
            'MgSO4': 120.366000,            // 24.305 + 32.065 + 4*15.999
            '(NH4)6Mo7O24·4H2O': 1235.86,    // 6(14.0067 + 4*1.007940) + 7*95.96 + 24*15.999 + 4(2*1.007940 + 15.999)
            '(NH4)2MoO4': 196.0354,  // (2 * (14.0067 + 4 * 1.00794)) + 95.96 + (4 * 15.999)

            // 元素
            'N': 14.006700,
            'P': 30.973762,
            'K': 39.098300,
            'Ca': 40.078000,
            'Mg': 24.305000,
            'S': 32.065000,
            'Fe': 55.845000,
            'Mn': 54.938045,
            'Zn': 65.380000,
            'Cu': 63.546000,
            'B': 10.811000,
            'Mo': 95.960000,
            'Cl': 35.453000,
            
            // 常用計算值
            'H': 1.007940,
            'O': 15.999000,
            'Na': 22.989770,
            'C': 12.010700,
            'H2O': 18.015340    // 2*1.007940 + 15.999
        };

        // 肥料成分對照表(以重量比例表示)
        const fertilizerComposition = {
            // 大量元素肥料
            'Ca(NO3)2·4H2O': {
                'Ca': 0.169715,  // 40.078 / 236.149920 = 16.97% Ca
                'N': 0.118721    // (2 * 14.0067) / 236.149920 = 11.87% N
            },
            'KNO3': {
                'K': 0.386716,   // 39.0983 / 101.102530 = 38.67% K
                'N': 0.138486    // 14.0067 / 101.102530 = 13.85% N
            },
            'MgSO4·7H2O': {
                'Mg': 0.098611,  // 24.305 / 246.474780 = 9.86% Mg
                'S': 0.130095    // 32.065 / 246.474780 = 13.01% S
            },
            'NH4H2PO4': {
                'N': 0.121773,   // 14.0067 / 115.025738 = 12.18% N
                'P': 0.269278,   // 30.973762 / 115.025738 = 26.93% P
                'H': 0.035023    // (4 * 1.007940) / 115.025738 = 3.50% H
            },
            'Ca(H2PO4)2·H2O': {
                'Ca': 0.158987,  // 40.078 / 252.082802 = 15.90% Ca
                'P': 0.245848,   // (2 * 30.973762) / 252.082802 = 24.58% P
                'H': 0.008000    // (4 * 1.007940) / 252.082802 = 0.80% H
            },
            'KH2PO4': {
                'K': 0.287305,   // 39.0983 / 136.085838 = 28.73% K
                'P': 0.227605,   // 30.973762 / 136.085838 = 22.76% P
                'H': 0.014819    // (2 * 1.007940) / 136.085838 = 1.48% H
            },
            'Ca(NO3)2': {
                'Ca': 0.244497,  // 40.078 / 164.088400 = 24.45% Ca
                'N': 0.170744    // (2 * 14.0067) / 164.088400 = 17.07% N
            },
            'MgSO4': {
                'Mg': 0.201927,  // 24.305 / 120.366000 = 20.19% Mg
                'S': 0.266393    // 32.065 / 120.366000 = 26.64% S
            },

            // 微量元素肥料
            'C10H12FeN2NaO8·3H2O': {
                'Fe': 0.135498   // 55.845 / 412.147420 = 13.55% Fe
            },
            'H3BO3': {
                'B': 0.174842    // 10.811 / 61.833220 = 17.48% B
            },
            'MnCl2·4H2O': {
                'Mn': 0.277595,  // 54.938045 / 197.905360 = 27.76% Mn
                'Cl': 0.358521   // (2 * 35.453) / 197.905360 = 35.85% Cl
            },
            'ZnSO4·7H2O': {
                'Zn': 0.227379,  // 65.38 / 287.539780 = 22.74% Zn
                'S': 0.111515    // 32.065 / 287.539780 = 11.15% S
            },
            'CuSO4·5H2O': {
                'Cu': 0.254504,  // 63.546 / 249.685700 = 25.45% Cu
                'S': 0.128421    // 32.065 / 249.685700 = 12.84% S
            },
            'Na2MoO4·2H2O': {
                'Mo': 0.396610   // 95.96 / 241.950680 = 39.66% Mo
            },
            '(NH4)6Mo7O24·4H2O': {
                'N': 0.068033,   // (6 * 14.0067) / 1235.86 = 6.80% N
                'Mo': 0.543754   // (7 * 95.96) / 1235.86 = 54.38% Mo
            },
            '(NH4)2MoO4': {
                'N': 0.142935,   // (2 * 14.0067) / 196.0354 = 14.29% N
                'Mo': 0.489497   // (1 * 95.96) / 196.0354 = 48.95% Mo
            }
        };

        // 離子價數對照表(用於 meq 計算)
        const ionicCharges = {
            'N': -1,    // NO3- 形式
            'P': -1,    // H2PO4- 形式
            'K': +1,    // K+ 形式
            'Ca': +2,   // Ca2+ 形式
            'Mg': +2,   // Mg2+ 形式
            'S': -2,    // SO4-2 形式
            'Fe': +2,   // Fe2+ 形式
            'Mn': +2,   // Mn2+ 形式
            'Zn': +2,   // Zn2+ 形式
            'Cu': +2,   // Cu2+ 形式
            'B': +3,    // B3+ 形式
            'Mo': -2,   // MoO4-2 形式
            'Cl': -1    // Cl- 形式
        };

        const selectedFertilizers = [];

        // 定義肥料清單
        const fertilizerList = [
            { value: 'Ca(NO3)2·4H2O', label: '硝酸鈣(四水) Ca(NO3)2·4H2O' },
            { value: 'NH4H2PO4', label: '磷酸一銨 NH4H2PO4' },
            { value: 'MgSO4·7H2O', label: '硫酸鎂(七水) MgSO4·7H2O' },
            { value: 'Ca(H2PO4)2·H2O', label: '磷酸一鈣(一水) Ca(H2PO4)2·H2O' },
            { value: 'Ca(NO3)2', label: '硝酸鈣 Ca(NO3)2' },
            { value: 'KNO3', label: '硝酸鉀 KNO3' },
            { value: 'MgSO4', label: '硫酸鎂 MgSO4' },
            { value: 'KH2PO4', label: '磷酸二氫鉀 KH2PO4' },
            { value: 'Fe-EDTA·3H2O', label: '螯合鐵(Fe-EDTA·3H2O)' },
            { value: 'H3BO3', label: '硼酸 H3BO3' },
            { value: 'MnCl2·4H2O', label: '氯化錳(四水) MnCl2·4H2O' },
            { value: 'ZnSO4·7H2O', label: '硫酸鋅(七水) ZnSO4·7H2O' },
            { value: 'CuSO4·5H2O', label: '硫酸銅(五水) CuSO4·5H2O' },
            { value: 'Na2MoO4·2H2O', label: '鉬酸鈉(二水) Na2MoO4·2H2O' },
            { value: '(NH4)6Mo7O24·4H2O', label: '仲鉬酸銨(四水) (NH4)6Mo7O24·4H2O' },
            { value: '(NH4)2MoO4', label: '鉬酸銨 (NH4)2MoO4' }
        ];
        
        // 添加反向計算的特定函數
        // ... 

        // 全局變量
        let availableFertilizers = [];
        let targetNutrients = {
            'N': { ppm: 0, meq: 0, mmol: 0 },
            'P': { ppm: 0, meq: 0, mmol: 0 },
            'K': { ppm: 0, meq: 0, mmol: 0 },
            'Ca': { ppm: 0, meq: 0, mmol: 0 },
            'Mg': { ppm: 0, meq: 0, mmol: 0 },
            'S': { ppm: 0, meq: 0, mmol: 0 },
            'Fe': { ppm: 0, meq: 0, mmol: 0 },
            'Mn': { ppm: 0, meq: 0, mmol: 0 },
            'Zn': { ppm: 0, meq: 0, mmol: 0 },
            'Cu': { ppm: 0, meq: 0, mmol: 0 },
            'B': { ppm: 0, meq: 0, mmol: 0 },
            'Mo': { ppm: 0, meq: 0, mmol: 0 },
            'Cl': { ppm: 0, meq: 0, mmol: 0 }
        };

        let currentInputMode = 'ppm';  // 預設使用 ppm 模式

        // 全域常數定義
        const SCALE_FACTOR = 1000000;     // 放大倍數(100萬倍)
        const STEP_SIZE = 0.01;           // 最小調整單位 (mg/L)
        const MAX_ITERATIONS = 1000;      // 最大迭代次數
        const TOLERANCE = 0.05;           // 允許誤差 5%
        const MIN_IMPROVEMENT = 0.001;    // 最小改善閾值

        // 調整後的步進大小(放大後的值)
        const SCALED_STEP_SIZE = Math.round(STEP_SIZE * SCALE_FACTOR);  // 放大後的最小調整單位

        // 初始化頁面
        document.addEventListener('DOMContentLoaded', function() {
            initializePage();
        });

        // 初始化頁面
        function initializePage() {
            // 初始化目標養分輸入表格
            initializeTargetNutrients();
            
            // 初始化所有可用肥料
            initializeAllFertilizers();
            
            // 初始化模式切換按鈕
            initializeInputModeSwitch();
        }

        // 初始化目標養分輸入表格
        function initializeTargetNutrients() {
            const tbody = document.getElementById('target-nutrients');
            tbody.innerHTML = '';
            
            Object.entries(targetNutrients).forEach(([element, values]) => {
                const tr = document.createElement('tr');
                tr.className = 'target-row';
                
                // 在元素符號後添加離子電荷標示
                const chargeSymbol = ionicCharges[element] > 0 ? 
                    `<sup>${ionicCharges[element]}+</sup>` : 
                    `<sup>${Math.abs(ionicCharges[element])}-</sup>`;
                
                tr.innerHTML = `
                    <td>${element}${chargeSymbol}</td>
                    <td><input type="number" class="target-input" data-element="${element}" data-type="ppm" value="0" step="0.0001"></td>
                    <td><input type="number" class="target-input" data-element="${element}" data-type="meq" value="0" step="0.000001"></td>
                    <td><input type="number" class="target-input" data-element="${element}" data-type="mmol" value="0" step="0.000001"></td>
                `;
                
                tbody.appendChild(tr);
            });
            
            // 添加輸入事件監聽器
            document.querySelectorAll('.target-input').forEach(input => {
                input.addEventListener('input', handleTargetInput);
            });
        }

        // 處理目標養分輸入
        function handleTargetInput(event) {
            const input = event.target;
            const element = input.dataset.element;
            const type = input.dataset.type;
            const value = parseFloat(input.value) || 0;
            
            // 更新目標值
            targetNutrients[element][type] = roundNumber(value, type === 'ppm' ? 4 : 6);
            
            // 自動計算其他值
            updateOtherValues(element, type, value);
        }

        // 更新其他相關值
        function updateOtherValues(element, changedType, value) {
            const inputs = document.querySelectorAll(`.target-input[data-element="${element}"]`);
            const molecularWeight = molecularWeights[element];
            const charge = Math.abs(ionicCharges[element]);
            
            inputs.forEach(input => {
                if (input.dataset.type !== changedType) {
                    let newValue = 0;
                    switch (changedType) {
                        case 'ppm':
                            if (input.dataset.type === 'mmol') {
                                newValue = value / molecularWeight;
                            } else if (input.dataset.type === 'meq') {
                                newValue = (value / molecularWeight) * charge;
                            }
                            break;
                        case 'meq':
                            if (input.dataset.type === 'mmol') {
                                newValue = value / charge;
                            } else if (input.dataset.type === 'ppm') {
                                newValue = (value / charge) * molecularWeight;
                            }
                            break;
                    }
                    input.value = formatNumber(newValue, input.dataset.type === 'ppm' ? 4 : 6);
                    targetNutrients[element][input.dataset.type] = roundNumber(newValue, input.dataset.type === 'ppm' ? 4 : 6);
                }
            });
        }

        // 添加新的初始化函數
        function initializeInputModeSwitch() {
            const buttons = document.querySelectorAll('.mode-btn');
            buttons.forEach(button => {
                button.addEventListener('click', function() {
                    const mode = this.dataset.mode;
                    setInputMode(mode);
                    
                    // 更新按鈕狀態
                    buttons.forEach(btn => btn.classList.remove('active'));
                    this.classList.add('active');
                });
            });
            
            // 初始設置
            setInputMode(currentInputMode);
        }

        // 設置輸入模式
        function setInputMode(mode) {
            currentInputMode = mode;
            const inputs = document.querySelectorAll('.target-input');
            
            inputs.forEach(input => {
                if (input.dataset.type === 'mmol') {
                    // mmol 始終禁用,但保持顯示
                    input.disabled = true;
                    input.style.backgroundColor = '#f7fafc';
                } else if (input.dataset.type === mode) {
                    // 啟用當前模式的輸入
                    input.disabled = false;
                    input.style.backgroundColor = 'white';
                } else {
                    // 禁用其他模式的輸入
                    input.disabled = true;
                    input.style.backgroundColor = '#f7fafc';
                }
            });
        }

        // 精度處理工具函數
        function roundNumber(value, precision = 3) {
            if (typeof value !== 'number' || isNaN(value)) return 0;
            const multiplier = Math.pow(10, precision);
            // 使用四捨六入五成雙規則
            const roundedValue = Math.round(value * multiplier) / multiplier;
            return roundedValue;
        }

        // 格式化顯示數值
        function formatNumber(value, precision = 3) {
            const roundedValue = roundNumber(value, precision);
            // 確保顯示指定的小數位數
            return roundedValue.toFixed(precision);
        }

        // 初始化所有可用肥料
        function initializeAllFertilizers() {
            availableFertilizers = fertilizerList.map(fertilizer => ({
                formula: fertilizer.value,
                amount: 0
            }));
            updateFertilizerList();
        }

        // 更新肥料列表顯示
        function updateFertilizerList() {
            const container = document.getElementById('available-fertilizers');
            
            const ul = document.createElement('ul');
            availableFertilizers.forEach((fertilizer, index) => {
                const li = document.createElement('li');
                const label = fertilizerList.find(f => f.value === fertilizer.formula)?.label || fertilizer.formula;
                
                li.innerHTML = `
                    <div class="fertilizer-info">
                        <span class="formula">${label}</span>
                        <div class="amount">
                            <span class="amount-display">${fertilizer.amount.toFixed(2)} g/L</span>
                        </div>
                    </div>
                `;
                ul.appendChild(li);
            });
            
            container.innerHTML = '';
            container.appendChild(ul);
        }

        // 執行反向計算
        async function calculateFertilizerAmounts() {
            // 1. 準備數據
            const targetData = prepareTargetData();
            if (Object.keys(targetData).length === 0) {
                alert('請設定至少一個目標養分含量');
                return;
            }
            
            const fertilizerMatrix = prepareFertilizerMatrix();
            const constraints = prepareConstraintMatrix(targetData, fertilizerMatrix);
            
            try {
                // 使用動態規劃求解器
                const solver = new DPSolver(targetData, fertilizerMatrix, constraints);
                const solution = solver.solve();
                
                // 更新結果
                updateCalculationResults(solution);
                
            } catch (error) {
                alert('無法找到合適的解決方案,請調整目標值');
                console.error('計算錯誤:', error);
            }
        }

        // 檢查解是否有效
        function isValidSolution(solution) {
            // 檢查是否所有必需的元素都達到目標值
            return Object.entries(targetNutrients).every(([element, values]) => {
                if (values.ppm <= 0) return true; // 跳過目標值為 0 的元素
                const calculated = calculateElementAmount(element, solution);
                return Math.abs(calculated - values.ppm) / values.ppm < 0.01; // 允許 1% 的誤差
            });
        }

        // 計算某個元素的實際含量
        function calculateElementAmount(element, solution) {
            let amount = 0;
            Object.entries(solution).forEach(([formula, weight]) => {
                const actualFormula = fertilizerAliases[formula] || formula;
                const composition = fertilizerComposition[actualFormula];
                if (composition && composition[element]) {
                    amount += weight * composition[element];
                }
            });
            return amount;
        }

        // 更新計算結果
        function updateCalculationResults(solution) {
            availableFertilizers = availableFertilizers.map(fert => ({
                ...fert,
                amount: solution[fert.formula] || 0
            }));
            
            updateFertilizerList();
            
            // 可以添加更詳細的結果顯示,如實際達到的養分含量等
        }

        // 準備目標養分數據
        function prepareTargetData() {
            const targetData = {};
            Object.entries(targetNutrients).forEach(([element, values]) => {
                if (values[currentInputMode] > 0) {
                    targetData[element] = {
                        target: values[currentInputMode],
                        tolerance: values[currentInputMode] * TOLERANCE_PERCENTAGE,  // 改為5%誤差
                        unit: currentInputMode,
                        min: values[currentInputMode] * (1 - TOLERANCE_PERCENTAGE),
                        max: values[currentInputMode] * (1 + TOLERANCE_PERCENTAGE)
                    };
                }
            });
            
            if (Object.keys(targetData).length === 0) {
                throw new Error('未設定任何目標養分含量');
            }
            
            return targetData;
        }

        // 準備肥料成分矩陣
        function prepareFertilizerMatrix() {
            const matrix = {};
            const validFertilizers = availableFertilizers.filter(fert => {
                const actualFormula = fertilizerAliases[fert.formula] || fert.formula;
                return fertilizerComposition[actualFormula] !== undefined;
            });

            if (validFertilizers.length === 0) {
                throw new Error('沒有可用的肥料');
            }

            validFertilizers.forEach(fert => {
                const actualFormula = fertilizerAliases[fert.formula] || fert.formula;
                const composition = fertilizerComposition[actualFormula];
                matrix[fert.formula] = {
                    composition: {},
                    price: fertilizerPrices[actualFormula] || 0  // 添加價格信息
                };
                
                Object.entries(composition).forEach(([element, content]) => {
                    if (element in targetNutrients && content > 0) {
                        matrix[fert.formula].composition[element] = content;
                    }
                });
            });

            return matrix;
        }

        // 建立約束條件矩陣
        function prepareConstraintMatrix(targetData, fertilizerMatrix) {
            const constraints = {
                elements: Object.keys(targetData),
                fertilizers: Object.keys(fertilizerMatrix),
                matrix: {},
                bounds: targetData,
                minAmount: 0,
                maxAmount: 10,
                totalMaxAmount: 20,
                prices: {}  // 添加價格信息
            };
            
            // 建立元素-肥料對應矩陣
            constraints.elements.forEach(element => {
                constraints.matrix[element] = {};
                constraints.fertilizers.forEach(fertilizer => {
                    constraints.matrix[element][fertilizer] = 
                        fertilizerMatrix[fertilizer].composition[element] || 0;
                });
            });
            
            // 添加價格訊息
            constraints.fertilizers.forEach(fertilizer => {
                constraints.prices[fertilizer] = fertilizerMatrix[fertilizer].price;
            });
            
            return constraints;
        }

        // 添加在全局常數區域
        const TOLERANCE_PERCENTAGE = 0.05; // 5% 誤差
        const fertilizerPrices = {
            'Ca(NO3)2·4H2O': 50,    // 硝酸鈣(四水),非現況價格
            'NH4H2PO4': 80,          // 磷酸一銨,非現況價格
            'MgSO4·7H2O': 20,        // 硫酸鎂(七水),非現況價格
            'Ca(H2PO4)2·H2O': 60,    // 磷酸一鈣(一水),非現況價格
            'Ca(NO3)2': 999,         // 硝酸鈣,尚未提供價格
            'KNO3': 30,              // 硝酸鉀,非現況價格
            'MgSO4': 999,            // 硫酸鎂,尚未提供價格
            'KH2PO4': 999,           // 磷酸二氫鉀,尚未提供價格
            'Fe-EDTA·3H2O': 500,     // 螯合鐵,非現況價格
            'H3BO3': 60,             // 硼酸,非現況價格
            'MnCl2·4H2O': 55,        // 氯化錳(四水),非現況價格
            'ZnSO4·7H2O': 45,        // 硫酸鋅(七水),非現況價格
            'CuSO4·5H2O': 40,        // 硫酸銅(五水),非現況價格
            'Na2MoO4·2H2O': 1400,    // 鉬酸鈉(二水),非現況價格
            '(NH4)6Mo7O24·4H2O': 999, // 仲鉬酸銨(四水),尚未提供價格
            '(NH4)2MoO4': 999        // 鉬酸銨,尚未提供價格
        };

        // 計算特定解的總成本
        function calculateTotalCost(solution, fertilizerMatrix) {
            let totalCost = 0;
            Object.entries(solution).forEach(([formula, amount]) => {
                const actualFormula = fertilizerAliases[formula] || formula;
                const price = fertilizerMatrix[formula].price;
                totalCost += amount * price;  // amount 是 g/L,需要轉換為 kg
            });
            return totalCost;
        }

        // 計算解的有效性(考慮誤差範圍)
        function isValidSolution(solution, targetData) {
            return Object.entries(targetData).every(([element, data]) => {
                const calculated = calculateElementAmount(element, solution);
                return calculated >= data.min && calculated <= data.max;
            });
        }

        class FertilizerSolver {
            constructor(targetData, fertilizerMatrix, constraints) {
                this.targetData = targetData;
                this.fertilizerMatrix = fertilizerMatrix;
                this.constraints = constraints;
                this.stepSize = STEP_SIZE;
                this.bestSolution = null;
                this.bestCost = Infinity;
                this.currentIteration = 0;
                
                // 添加精確度控制
                this.precision = {
                    amount: 0.01,      // mg/L
                    cost: 0.001,       // 成本計算精確度
                    nutrient: 0.01     // 養分含量計算精確度
                };
            }

            // 四捨五入到指定精確度
            round(value, precision) {
                return Math.round(value / precision) * precision;
            }

            // 評估當前解的品質(考慮精確度)
            evaluateSolution(solution) {
                // 檢查是否滿足所有養分需求
                if (!this.isValidSolution(solution)) {
                    return Infinity;
                }
                
                // 計算總成本(考慮精確度)
                const cost = this.calculateTotalCost(solution);
                return this.round(cost, this.precision.cost);
            }
        }

        class DPSolver extends FertilizerSolver {
            constructor(targetData, fertilizerMatrix, constraints) {
                super(targetData, fertilizerMatrix, constraints);
                console.log('初始化求解器(放大前):', {
                    targetData,
                    fertilizerMatrix,
                    constraints
                });
                // debugger; // 中斷點:初始化(放大前)

                // 放大目標數值
                this.scaledTargetData = {};
                Object.entries(this.targetData).forEach(([element, data]) => {
                    this.scaledTargetData[element] = {
                        min: Math.round(data.min * SCALE_FACTOR),
                        max: Math.round(data.max * SCALE_FACTOR),
                        target: Math.round(data.target * SCALE_FACTOR)
                    };
                });

                // 放大肥料矩陣
                this.scaledMatrix = {};
                Object.entries(this.constraints.matrix).forEach(([element, fertilizers]) => {
                    this.scaledMatrix[element] = {};
                    Object.entries(fertilizers).forEach(([fertilizer, value]) => {
                        this.scaledMatrix[element][fertilizer] = Math.round(value * SCALE_FACTOR);
                    });
                });

                // 初始化狀態
                this.dpStates = new Map();
                this.currentState = {
                    nutrients: {},          // 當前養分含量
                    cost: 0,               // 當前成本
                    solution: {}           // 當前解
                };

                // 初始化當前養分含量(使用放大後的值)
                this.constraints.elements.forEach(element => {
                    this.currentState.nutrients[element] = 0;
                });

                console.log('初始化完成(放大後):', {
                    scaledTargetData: this.scaledTargetData,
                    scaledMatrix: this.scaledMatrix,
                    currentState: this.currentState
                });
                // debugger; // 中斷點:初始化完成
            }

            // 檢查是否達到目標(使用放大後的值)
            isTargetReached(state) {
                console.log('檢查目標達成狀態:', state);
                // debugger; // 中斷點:目標檢查

                return this.constraints.elements.every(element => {
                    const target = this.scaledTargetData[element];
                    const current = state.nutrients[element];
                    const reached = current >= target.min && current <= target.max;
                    console.log(`元素 ${element}:`, {
                        current,
                        min: target.min,
                        max: target.max,
                        reached
                    });
                    return reached;
                });
            }

            // 計算新狀態(使用放大後的值)
            calculateNewState(currentState, fertilizer, amount) {
                console.log('計算新狀態:', {
                    currentState,
                    fertilizer,
                    amount: amount / SCALE_FACTOR // 顯示實際值
                });
                // debugger; // 中斷點:狀態計算

                const newState = {
                    nutrients: {...currentState.nutrients},
                    cost: currentState.cost,
                    solution: {...currentState.solution}
                };

                // 使用放大後的矩陣計算
                this.constraints.elements.forEach(element => {
                    const contribution = this.scaledMatrix[element][fertilizer] * (amount / SCALE_FACTOR);
                    newState.nutrients[element] = Math.round(newState.nutrients[element] + contribution);
                });

                // 更新成本(使用原始價格)
                const fertilizerPrice = this.constraints.prices[fertilizer];
                newState.cost += fertilizerPrice * (amount / SCALE_FACTOR);
                newState.solution[fertilizer] = (newState.solution[fertilizer] || 0) + (amount / SCALE_FACTOR);

                return newState;
            }

            // 主要求解函數
            solve() {
                console.log('開始求解過程');
                // debugger; // 中斷點:求解開始

                const initialKey = this.generateStateKey(this.currentState);
                this.dpStates.set(initialKey, this.currentState);

                let iteration = 0;
                let improved = true;

                while (improved && iteration < MAX_ITERATIONS) {
                    improved = false;
                    iteration++;
                    console.log(`開始第 ${iteration} 次迭代`);
                    // debugger; // 中斷點:迭代開始

                    // 遍歷當前所有狀態
                    for (const [stateKey, state] of this.dpStates) {
                        // 如果已達到目標且成本更低,更新最佳解
                        if (this.isTargetReached(state) && state.cost < this.bestCost) {
                            console.log('找到更好的解:', {
                                oldCost: this.bestCost,
                                newCost: state.cost,
                                solution: state.solution
                            });
                            // debugger; // 中斷點:找到更好的解

                            this.bestCost = state.cost;
                            this.bestSolution = {...state.solution};
                            improved = true;
                            continue;
                        }

                        // 嘗試添加每種肥料
                        for (const fertilizer of this.constraints.fertilizers) {
                            const newState = this.calculateNewState(state, fertilizer, SCALED_STEP_SIZE);
                            const newKey = this.generateStateKey(newState);

                            if (!this.dpStates.has(newKey) || this.dpStates.get(newKey).cost > newState.cost) {
                                console.log('更新狀態:', {
                                    fertilizer,
                                    amount: SCALED_STEP_SIZE / SCALE_FACTOR, // 顯示實際值
                                    oldCost: this.dpStates.get(newKey)?.cost,
                                    newCost: newState.cost
                                });
                                // debugger; // 中斷點:狀態更新

                                this.dpStates.set(newKey, newState);
                                improved = true;
                            }
                        }
                    }

                    console.log(`第 ${iteration} 次迭代結束`, {
                        improved,
                        statesCount: this.dpStates.size,
                        bestCost: this.bestCost
                    });
                }

                if (!this.bestSolution) {
                    throw new Error('無法找到有效解');
                }

                console.log('求解完成', {
                    iterations: iteration,
                    finalCost: this.bestCost,
                    solution: this.bestSolution
                });
                // debugger; // 中斷點:求解完成

                return this.bestSolution;
            }

            // 生成狀態的唯一鍵值
            generateStateKey(state) {
                console.log('生成狀態鍵值,當前狀態:', state);
                // debugger; // 中斷點:生成鍵值
                
                // 使用養分含量生成鍵值(放大後的值)
                const key = this.constraints.elements
                    .map(element => Math.round(state.nutrients[element]))  // 確保是整數
                    .join('|');
                    
                console.log('生成的鍵值:', key);
                return key;
            }
        }
    </script>
</body>
</html>