1 (***************************************************************************
2 * Copyright (C) 2004 by Thomas Nagy *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************)
29 (* columns : vars + formula | lines : chemical elements *)
30 val mutable numtbl
= Array.make_matrix
0 0 0
31 val mutable strtbl
= Array.make
0 ""
32 val mutable vartbl
= Array.make
0 ""
33 val mutable soltbl
= Array.make
0 0
34 val mutable m_solved
= false
35 val mutable m_middle
= 0
37 (* val mutable (table:int array array) = [||] *)
39 (* lines : i : chem element *)
40 (* columns : vars j *)
41 method getsize_i
() = Array.length numtbl
42 method getsize_j
() = if (self#getsize_i
() > 0) then Array.length numtbl
.(0) else 0
44 method getline j
= numtbl
.(j
)
46 method getformula k
= strtbl
.(k
)
47 method getvar k
= vartbl
.(k
)
48 method getsol k
= soltbl
.(k
)
50 method setsol k v
= soltbl
.(k
) <- v
51 method isSolved
() = m_solved
53 method get_eq_sol
() =
55 for j
=0 to (self#getsize_j
() -1) do
56 if (j
== m_middle
) then str := (!str)^
" -> "
57 else if (j
>0 && j
<self#getsize_j
()) then str := (!str)^
" + ";
59 str := (!str)^
"<b>"^string_of_int
(self#getsol j
)^
"</b> "^
(self#getformula j
);
63 method get_eq_orig
() =
65 for j
=0 to (self#getsize_j
() -1) do
66 if (j
== m_middle
) then str := (!str)^
" -> "
67 else if (j
>0 && j
<self#getsize_j
()) then str := (!str)^
" + ";
69 str := (!str)^
"<b>"^
(self#getvar j
)^
"</b> "^
(self#getformula j
);
73 method private init i j
= numtbl
<- Array.make_matrix i j
0;
74 strtbl
<- Array.make j
"";
75 vartbl
<- Array.make j
"";
76 soltbl
<- Array.make j
0
82 Printf.printf
"--- start print_all ---\n";
83 for i
= 0 to (self#getsize_i
())-1 do
84 for j
= 0 to (self#getsize_j
())-1 do
85 Printf.printf
"%d " (numtbl
.(i
).(j
));
89 Printf.printf
"--- end print_all ---\n";
92 (* build the matrix to solve *)
93 method build
(lst
:listitems
) =
94 let nb_symbols = ref 0 in
95 let item_array = Array.of_list lst
in
96 let record:(string, int) Hashtbl.t
= Hashtbl.create
10 in
97 let nb_items = ref (Array.length
item_array) in
98 for i
=0 to !nb_items-1 do
99 Hashtbl.iter
(fun sym _
->
100 (* take all chemical elements but simplify ions (+ or -) into + *)
101 let symprocessed = if String.contains sym '
+'
|| String.contains sym '
-'
104 if not
(Hashtbl.mem
record symprocessed) then begin
105 Hashtbl.add
record symprocessed !nb_symbols;
106 nb_symbols := !nb_symbols+1
108 ) item_array.(i
).itbl
.hashtbl
111 (* initialize the matrix *)
112 self#init
(!nb_symbols) (!nb_items);
114 (* process each atom*)
115 for i
=0 to !nb_items-1 do
116 (* find the middle (->) - nothing to do with the others things in this loop *)
117 if (item_array.(i
).sign
<0 && i
>0) then (if (item_array.(i
-1).sign
>0) then m_middle
<-i
);
119 (* store the molecule formula *)
120 vartbl
.(i
) <- item_array.(i
).ikey
;
121 strtbl
.(i
) <- item_array.(i
).itbl
.formula
;
123 (* for each molecule, process the atoms *)
124 Hashtbl.iter
(fun sym qte
->
126 if String.contains sym '
+'
|| String.contains sym '
-'
then begin
127 (* it is an electric charge *)
128 let chargesign = if String.contains sym '
-'
then -1 else 1 in
129 let line_idx = (Hashtbl.find
record "+") in
130 numtbl
.(line_idx).(i
) <- qte
* item_array.(i
).sign
* chargesign
133 (* check if the atom is already there *)
134 let line_idx = (Hashtbl.find
record sym
) in
135 numtbl
.(line_idx).(i
) <- (qte
* item_array.(i
).sign
)
137 ) item_array.(i
).itbl
.hashtbl