Merge: doc: fixed some typos and other misc. corrections
[nit.git] / examples / draw_operation.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2012-2013 Alexis Laferrière <alexis.laf@xymus.net>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Sample program which draws an arithmetic operation to the terminal
18 #
19 # Output (and input) example:
20 # ~~~nitish
21 # Left operand: 23
22 # Right operand: 15
23 # Operator (+, -, *, /, %): +
24 # Char to display: #
25 # Size of text: 5
26 # Space between digits: 1
27 # ##### #####
28 # # #
29 # ##### #####
30 # # #
31 # ##### #####
32 #
33 # # #####
34 # + ## #
35 # +++++ # #####
36 # + # #
37 # ##### #####
38 #
39 # __________________
40 #
41 # ##### #####
42 # # # #
43 # ##### #####
44 # # # #
45 # ##### #####
46 # ~~~
47 module draw_operation
48
49 `{
50 #include <math.h>
51 `}
52
53 redef enum Int
54 fun n_chars: Int `{
55 int c;
56 if ( abs(self) >= 10 )
57 c = 1+(int)log10f( (float)abs(self) );
58 else
59 c = 1;
60 if ( self < 0 ) c ++;
61 return c;
62 `}
63 end
64
65 redef enum Char
66 fun as_operator(a, b: Int): Int
67 do
68 if self == '+' then return a + b
69 if self == '-' then return a - b
70 if self == '*' then return a * b
71 if self == '/' then return a / b
72 if self == '%' then return a % b
73 abort
74 end
75
76 fun override_dispc: Bool
77 do
78 return self == '+' or self == '-' or self == '*' or self == '/' or self == '%'
79 end
80
81 fun lines(s: Int): Array[Line]
82 do
83 if self == '+' then
84 return [new Line(new P(0,s/2),1,0,s), new Line(new P(s/2,1),0,1,s-2)]
85 else if self == '-' then
86 return [new Line(new P(0,s/2),1,0,s)]
87 else if self == '*' then
88 var lines = new Array[Line]
89 for y in [1..s-1[ do
90 lines.add( new Line(new P(1,y), 1,0,s-2) )
91 end
92 return lines
93 else if self == '/' then
94 return [new Line(new P(s-1,0), -1,1, s )]
95 else if self == '%' then
96 var q4 = s/4
97 var lines = [new Line(new P(s-1,0),-1,1,s)]
98 for l in [0..q4[ do
99 lines.append([ new Line( new P(0,l), 1,0,q4), new Line( new P(s-1,s-1-l), -1,0,q4) ])
100 end
101 return lines
102 else if self == '1' then
103 return [new Line(new P(s/2,0), 0,1,s),new Line(new P(0,s-1),1,0,s),
104 new Line( new P(s/2,0),-1,1,s/2)]
105 else if self == '2' then
106 return [new Line(new P(0,0), 1,0,s),new Line(new P(s-1,0),0,1,s/2),
107 new Line( new P(0,s-1),1,0,s), new Line( new P(0,s/2), 0,1,s/2),
108 new Line( new P(0,s/2), 1,0,s)]
109 else if self == '3' then
110 return [new Line(new P(0,0), 1,0,s),new Line(new P(s-1,0),0,1,s),
111 new Line( new P(0,s-1),1,0,s), new Line( new P(0,s/2), 1,0,s)]
112 else if self == '4' then
113 return [new Line(new P(s-1,0),0,1,s), new Line( new P(0,0), 0,1,s/2),
114 new Line( new P(0,s/2), 1,0,s)]
115 else if self == '5' then
116 return [new Line(new P(0,0), 1,0,s),new Line(new P(s-1,s/2),0,1,s/2),
117 new Line( new P(0,s-1),1,0,s), new Line( new P(0,0), 0,1,s/2),
118 new Line( new P(0,s/2), 1,0,s)]
119 else if self == '6' then
120 return [new Line(new P(0,0), 1,0,s),new Line(new P(s-1,s/2),0,1,s/2),
121 new Line( new P(0,s-1),1,0,s), new Line( new P(0,0), 0,1,s),
122 new Line( new P(0,s/2), 1,0,s)]
123 else if self == '7' then
124 var tl = new P(0,0)
125 var tr = new P(s-1,0)
126 return [new Line(tl, 1,0,s), new Line(tr,-1,1,s)]
127 else if self == '8' then
128 return [new Line(new P(0,0), 1,0,s),new Line(new P(s-1,0),0,1,s),
129 new Line( new P(0,s-1),1,0,s), new Line( new P(0,0), 0,1,s),
130 new Line( new P(0,s/2), 1,0,s)]
131 else if self == '9' then
132 return [new Line(new P(0,0), 1,0,s),new Line(new P(s-1,0),0,1,s),
133 new Line( new P(0,s-1),1,0,s), new Line( new P(0,0), 0,1,s/2),
134 new Line( new P(0,s/2), 1,0,s)]
135 else if self == '0' then
136 return [new Line(new P(0,0), 1,0,s),new Line(new P(s-1,0),0,1,s),
137 new Line( new P(0,s-1),1,0,s), new Line( new P(0,0), 0,1,s)]
138 end
139 return new Array[Line]
140 end
141 end
142
143 class P
144 var x : Int
145 var y : Int
146 end
147
148 redef class String
149 # hack is to support a bug in the evaluation software
150 fun draw(dispc: Char, size, gap: Int, hack: Bool)
151 do
152 var w = size * length +(length-1)*gap
153 var h = size
154 var map = new Array[Array[Char]]
155 for x in [0..w[ do
156 map[x] = new Array[Char].filled_with( ' ', h )
157 end
158
159 var ci = 0
160 for c in self.chars do
161 var local_dispc
162 if c.override_dispc then
163 local_dispc = c
164 else
165 local_dispc = dispc
166 end
167
168 var lines = c.lines( size )
169 for line in lines do
170 var x = line.o.x+ci*size
171 x += ci*gap
172 var y = line.o.y
173 for s in [0..line.len[ do
174 assert map.length > x and map[x].length > y else print "setting {x},{y} as {local_dispc}"
175 map[x][y] = local_dispc
176 x += line.step_x
177 y += line.step_y
178 end
179 end
180
181 ci += 1
182 end
183
184 if hack then
185 for c in [0..size[ do
186 map[c][0] = map[map.length-size+c][0]
187 map[map.length-size+c][0] = ' '
188 end
189 end
190
191 for y in [0..h[ do
192 for x in [0..w[ do
193 printn map[x][y]
194 end
195 print ""
196 end
197 end
198 end
199
200 class Line
201 var o : P
202 var step_x : Int
203 var step_y : Int
204 var len : Int
205 end
206
207 var a
208 var b
209 var op_char
210 var disp_char
211 var disp_size
212 var disp_gap
213
214 if "NIT_TESTING".environ == "true" then
215 a = 567
216 b = 13
217 op_char = '*'
218 disp_char = 'O'
219 disp_size = 8
220 disp_gap = 1
221 else
222 printn "Left operand: "
223 a = gets.to_i
224
225 printn "Right operand: "
226 b = gets.to_i
227
228 printn "Operator (+, -, *, /, %): "
229 op_char = gets.chars[0]
230
231 printn "Char to display: "
232 disp_char = gets.chars[0]
233
234 printn "Size of text: "
235 disp_size = gets.to_i
236
237 printn "Space between digits: "
238 disp_gap = gets.to_i
239 end
240
241 var result = op_char.as_operator( a, b )
242
243 var len_a = a.n_chars
244 var len_b = b.n_chars
245 var len_res = result.n_chars
246 var max_len = len_a.max( len_b.max( len_res ) ) + 1
247
248 # draw first line
249 var d = max_len - len_a
250 var line_a = ""
251 for i in [0..d[ do line_a += " "
252 line_a += a.to_s
253 line_a.draw( disp_char, disp_size, disp_gap, false )
254
255 print ""
256 # draw second line
257 d = max_len - len_b-1
258 var line_b = op_char.to_s
259 for i in [0..d[ do line_b += " "
260 line_b += b.to_s
261 line_b.draw( disp_char, disp_size, disp_gap, false )
262
263 # draw -----
264 print ""
265 for i in [0..disp_size*max_len+(max_len-1)*disp_gap] do
266 printn "_"
267 end
268 print ""
269 print ""
270
271 # draw result
272 d = max_len - len_res
273 var line_res = ""
274 for i in [0..d[ do line_res += " "
275 line_res += result.to_s
276 line_res.draw( disp_char, disp_size, disp_gap, false )