Intro wrappers to work with textures, shaders, framebuffers and renderbuffers, synchronize with server and set clear values of buffers. Update most of the remaining enumerations and some more services to the new API style. Add a makefile to generate a wrapper stub from the local GLES2/gl2.h header file.
FYI, there's approximatly only 65 functions left to wrap, out of 141.
Pull-Request: #1743
Reviewed-by: Jean Privat <jean@pryen.org>
var randompoints = generate_points(n + 1)
var points = randompoints.clone
points.remove_at(points.length -1)
- var poly = new ConvexPolygon.with_vertices(randompoints)
+ var poly = new ConvexPolygon(randompoints)
poly.sort_ccw
poly.add_vertex(randompoints.last)
end
# Bench the convexity verificatioon
fun bench_convexity(n : Int) do
var randompoints = generate_points(n)
- var poly = new ConvexPolygon.with_vertices(randompoints)
+ var poly = new ConvexPolygon(randompoints)
poly.sort_ccw
poly.is_convex
end
fun bench_contain(n : Int) do
srand_from(50)
var randompoints = generate_points(n)
- var poly = new ConvexPolygon.with_vertices(randompoints)
+ var poly = new ConvexPolygon(randompoints)
poly.sort_ccw
var point = new Point[Float](0.0, 0.0)
poly.contain(point)
fun bench_sorting(n : Int) do
var randompoints = generate_points(n)
randompoints.shuffle
- var poly = new ConvexPolygon.with_vertices(randompoints)
+ var poly = new ConvexPolygon(randompoints)
poly.sort_ccw
end
fun bench_intersection(n : Int) do
var r1 = generate_points(n)
var r2 = generate_points(n)
- var poly1 = new ConvexPolygon.with_vertices(r1)
- var poly2 = new ConvexPolygon.with_vertices(r2)
+ var poly1 = new ConvexPolygon(r1)
+ var poly2 = new ConvexPolygon(r2)
poly1.sort_ccw
poly2.sort_ccw
poly1.intersects(poly2)
# Interpreter for Brainfuck source code.
class BFInterpreter
# Data cells
- var dr = new Array[Char]
+ var dr = new Array[Byte]
# Data pointer
var dp = 0
# Instruction pointer
var ip = 0
# The program being interpreted
- var program: String
-
- # Contains the set of valid instructions, used in next
- var valid_instr: Set[Char] is noinit
+ var program: Bytes
# Create an interpreter for `program`.
init do
- valid_instr = new HashSet[Char]
- valid_instr.add_all "><[].,+-".chars
- dr.add 0.ascii
+ dr.add 0u8
end
# Create an interpreter for the file located at `path`.
init from_file(path: String) do
var ifs = new FileReader.open(path)
- init(ifs.read_all)
+ init(ifs.read_all_bytes)
end
# Starts the interpretation of the loaded program
loop
if ip >= program.length then break
eval
- next
- end
- end
-
- # Go to the next executable instruction
- fun next do
- ip += 1
- while ip < program.length and not valid_instr.has(program[ip]) do
ip += 1
end
end
+
# Evaluates the current instruction
fun eval do
var instr = program[ip]
- if instr == '.' then printn dr[dp]
- if instr == '[' then
- if dr[dp] == 0.ascii then
+ if instr == '.'.ascii then printn dr[dp].ascii
+ if instr == '['.ascii then
+ if dr[dp] == 0u8 then
ip = find_matching_rbra
return
end
end
- if instr == ']' then
- if dr[dp] != 0.ascii then
+ if instr == ']'.ascii then
+ if dr[dp] != 0u8 then
ip = find_matching_lbra
return
end
end
- if instr == '>' then
+ if instr == '>'.ascii then
dp += 1
- if dp >= dr.length then dr.add(0.ascii)
+ if dp >= dr.length then dr.add(0u8)
end
- if instr == '<' then
+ if instr == '<'.ascii then
dp -= 1
if dp < 0 then abort
end
- if instr == '+' then
- dr[dp] = (dr[dp].ascii + 1).ascii
+ if instr == '+'.ascii then
+ dr[dp] = dr[dp] + 1u8
end
- if instr == '-' then
- dr[dp] = (dr[dp].ascii - 1).ascii
+ if instr == '-'.ascii then
+ dr[dp] = dr[dp] - 1u8
end
- if instr == ',' then
- dr[dp] = getc
+ if instr == ','.ascii then
+ dr[dp] = getc.ascii
end
end
var lbracnt = 0
loop
if pos > program.length then abort
- if program[pos] == ']' then
+ if program[pos] == ']'.ascii then
if lbracnt > 0 then
lbracnt -= 1
else
break
end
end
- if program[pos] == '[' then lbracnt += 1
+ if program[pos] == '['.ascii then lbracnt += 1
pos += 1
end
return pos
var rbracnt = 0
loop
if pos < 0 then abort
- if program[pos] == '[' then
+ if program[pos] == '['.ascii then
if rbracnt > 0 then
rbracnt -= 1
else
break
end
end
- if program[pos] == ']' then rbracnt += 1
+ if program[pos] == ']'.ascii then rbracnt += 1
pos -= 1
end
return pos
else if c >= 'A' and c <= 'I' then
var t = self.get(x,y)
assert t != null
- t.update(c.ascii-'A'.ascii+1)
+ t.update(c.code_point-'A'.code_point+1)
t.fixed = true
x += 1
else if c >= 'a' and c <= 'i' then
var t = self.get(x,y)
assert t != null
- t.update(c.ascii-'a'.ascii+1)
+ t.update(c.code_point-'a'.code_point+1)
x += 1
else if c >= '1' and c <= '9' then
rle = c.to_i
if k == 0 then
if t.fixed then c = '#'
else
- b.add(0x1b.ascii)
+ b.add(0x1b.code_point)
b.add('[')
b.append ansicols[k]
- c = (k + 'a'.ascii - 1).ascii
+ c = (k + 'a'.code_point - 1).code_point
if t.fixed then c = c.to_upper
b.append("m")
end
b.add(c)
if k != 0 then
- b.add(0x1b.ascii)
+ b.add(0x1b.code_point)
b.append("[0m")
end
--- /dev/null
+assets/images/
+res/
+src/drawing.nit
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+all: bin/memory
+
+bin/memory: assets/images/drawing.png src/*.nit
+ mkdir -p bin
+ ../../bin/nitc -o bin/memory src/memory.nit -m ../../lib/mnit/linux/linux.nit
+
+assets/images/drawing.png: art/drawing.svg
+ mkdir -p assets/images/
+ ../inkscape_tools/bin/svg_to_png_and_nit art/drawing.svg -a assets/ -s src/ -x 4
+
+res/drawable-ldpi/icon.png: art/icon.svg
+ mkdir -p res/
+ ../inkscape_tools/bin/svg_to_icons art/icon.svg --android --out res/
+
+android: bin/memory.apk
+bin/memory.apk: assets/images/drawing.png src/*.nit res/drawable-ldpi/icon.png
+ mkdir -p bin
+ ../../bin/nitc -o bin/memory.apk src/memory.nit -m ../../lib/mnit/android/android.nit -m ../../lib/android/landscape.nit
+
+android-release: assets/images/drawing.png src/*.nit res/drawable-ldpi/icon.png
+ mkdir -p bin
+ ../../bin/nitc -o bin/memory.apk src/memory.nit -m ../../lib/mnit/android/android.nit -m ../../lib/android/landscape.nit --release
--- /dev/null
+# Memorize Shapes and Colors
+
+A memory-based game where figures are cliqued in sequence by the computer and should be replayed by the player in the same order.
+As the player progresses, more figures are added and the sequences to remember become longer.
+
+The player can make up to 2 errors to solve a single level.
+At the 3rd error, the level has to be replayed.
+
+The game use a very simple user interface and features big figures with bright colors and simple distinguishable shapes; that makes it suitable for young children.
+
+The game offers three modes (difficulty level)
+
+Easy (for young children):
+
+* Start with 2 figures, 1 to remember
+* Figures are easily distinguishable
+* Figures remain on place
+* After 3 errors, the same level is replayed
+
+Medium (for normal player):
+
+* Like easy but:
+* Start with 3 figures, 3 to remember
+* Figures are moved after the sequence played by the computer
+* After 3 errors, a new level is produced
+
+Hard (for hypermnesic players)
+
+* Like medium but:
+* Figures use overlapping combinations of colors and shapes
+* Figures are shuffled completely
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="509.0834"
+ height="324.85132"
+ viewBox="0 0 509.08342 324.85131"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="drawing.svg"
+ inkscape:export-filename="/home/privat/prog/nit/contrib/memory/art/drawing.png"
+ inkscape:export-xdpi="900"
+ inkscape:export-ydpi="900">
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.4"
+ inkscape:cx="326.44213"
+ inkscape:cy="188.58838"
+ inkscape:document-units="pt"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1920"
+ inkscape:window-height="1136"
+ inkscape:window-x="1600"
+ inkscape:window-y="27"
+ inkscape:window-maximized="1"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:snap-text-baseline="false"
+ units="pt" />
+ <defs
+ id="defs4" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ transform="translate(-112.50514,-37.583924)"
+ id="layer1"
+ inkscape:groupmode="layer"
+ inkscape:label="Calque 1">
+ <path
+ transform="matrix(1.0790955,0,0,1.1325291,-9.0916016,-22.007078)"
+ inkscape:label="#path3338"
+ inkscape:transform-center-y="-3.9327809"
+ inkscape:transform-center-x="1.3947101"
+ d="m 180.81731,133.12338 -25.13223,-13.03035 -24.98194,13.31622 4.62632,-27.92877 -20.38433,-19.644302 27.99145,-4.230572 12.38374,-25.457066 12.67335,25.314133 28.03789,3.910967 -20.15889,19.87557 z"
+ inkscape:randomized="0"
+ inkscape:rounded="0"
+ inkscape:flatsided="false"
+ sodipodi:arg2="1.5650921"
+ sodipodi:arg1="0.9367736"
+ sodipodi:r2="21.315176"
+ sodipodi:r1="42.630352"
+ sodipodi:cy="98.778198"
+ sodipodi:cx="155.56349"
+ sodipodi:sides="5"
+ id="0star"
+ style="fill:#ffffff;fill-opacity:1;stroke:#808080;stroke-width:4.52288342;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:type="star" />
+ <ellipse
+ inkscape:label="#path3342"
+ ry="43.75"
+ rx="43.750004"
+ cy="87.475639"
+ cx="256.61908"
+ id="0circle"
+ style="fill:#ffffff;stroke:#808080;stroke-width:5.00000048;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <rect
+ inkscape:label="#rect3346"
+ y="44.975639"
+ x="319.36441"
+ height="81.250008"
+ width="81.250008"
+ id="0rect"
+ style="fill:#ffffff;stroke:#808080;stroke-width:5.00000048;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ transform="matrix(1.138458,0.01858784,-0.01944847,1.1911688,-113.46281,-38.903848)"
+ inkscape:label="#path3348"
+ inkscape:transform-center-y="-4.0794014"
+ inkscape:transform-center-x="0.47783259"
+ d="m 536.391,131.10309 -47.49475,0.72114 -15.36253,-44.947336 38.00017,-28.500132 38.84794,27.33329 z"
+ inkscape:randomized="0"
+ inkscape:rounded="0"
+ inkscape:flatsided="true"
+ sodipodi:arg2="1.5556138"
+ sodipodi:arg1="0.92729522"
+ sodipodi:r2="32.545895"
+ sodipodi:r1="40.406101"
+ sodipodi:cy="98.778206"
+ sodipodi:cx="512.14734"
+ sodipodi:sides="5"
+ id="0penta"
+ style="fill:#ffffff;stroke:#808080;stroke-width:4.2930603;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:type="star" />
+ <path
+ transform="matrix(0.9848695,-0.0389352,0.04401556,1.1133778,-29.129711,11.863574)"
+ inkscape:label="#path3350"
+ inkscape:transform-center-y="-5.2078962"
+ inkscape:transform-center-x="-1.6611955"
+ d="m 652.55851,129.08278 -88.77492,-3.29401 47.24016,-75.23433 z"
+ inkscape:randomized="0"
+ inkscape:rounded="0"
+ inkscape:flatsided="true"
+ sodipodi:arg2="1.6078845"
+ sodipodi:arg1="0.56068699"
+ sodipodi:r2="34.010933"
+ sodipodi:r1="51.289494"
+ sodipodi:cy="101.80866"
+ sodipodi:cx="609.12195"
+ sodipodi:sides="3"
+ id="0triangle"
+ style="fill:#ffffff;stroke:#808080;stroke-width:4.77111959;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:type="star" />
+ <g
+ transform="translate(-7.1428071,-28.263269)"
+ style="fill:#ffffff;stroke:#808080;stroke-width:5.00000048;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ inkscape:label="#g3356"
+ id="0cross">
+ <path
+ style="fill:#ffffff;stroke:#808080;stroke-width:5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 42.5625,125.5 0,31.25 -31.25,0 0,25 31.25,0 0,31.25 25,0 0,-31.25 31.25,0 0,-25 -31.25,0 0,-31.25 -25,0 z"
+ transform="translate(114.94512,48.417475)"
+ id="rect3352"
+ inkscape:connector-curvature="0" />
+ </g>
+ <rect
+ inkscape:label="#rect3341"
+ transform="matrix(0.68019493,0.73303128,-0.73365707,0.67951991,0,0)"
+ ry="0"
+ y="-93.236977"
+ x="286.09988"
+ height="61.163219"
+ width="62.66906"
+ id="0diamond"
+ style="fill:#ffffff;stroke:#808080;stroke-width:5.00000143;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ inkscape:label="#path3350"
+ inkscape:connector-curvature="0"
+ id="0moon"
+ d="m 368.00103,142.79236 a 50.857007,43.749388 0 0 0 -50.85758,43.75075 50.857007,43.749388 0 0 0 50.85758,43.74925 50.857007,43.749388 0 0 0 36.5966,-13.44214 37.525559,30.468323 0 0 1 -3.51512,0.16013 37.525559,30.468323 0 0 1 -37.52646,-30.46724 37.525559,30.468323 0 0 1 37.52646,-30.46873 37.525559,30.468323 0 0 1 3.56094,0.14501 50.857007,43.749388 0 0 0 -36.64242,-13.42703 z"
+ style="fill:#ffffff;stroke:#808080;stroke-width:5.00000048;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ inkscape:label="#path3356"
+ inkscape:connector-curvature="0"
+ id="0spiral"
+ d="m 467.10669,144.22922 c -20.15895,-0.32141 -38.9065,16.76425 -41.19858,37.60291 -3.86937,23.35281 16.7358,47.48676 39.64103,45.31644 12.20102,-0.76865 23.76919,-8.45705 29.03604,-20.00332 6.61043,-13.59525 3.19101,-31.78746 -8.72849,-41.00231 -11.91023,-9.84408 -31.5447,-7.79332 -40.34686,5.46911 -8.25602,11.53909 -5.3078,30.58816 7.47626,37.21364 10.28179,6.05468 25.63854,1.15001 29.0991,-11.11553 3.04684,-9.25632 -2.65279,-21.09349 -12.45674,-22.21563 -7.74971,-1.31975 -16.07358,6.63167 -13.65087,14.90034 1.37551,7.39459 14.12722,8.17257 14.08847,-0.22482 -0.0955,-2.72794 -2.63922,-5.69968 -5.32908,-4.79848 4.38499,-3.96292 10.36557,1.52768 9.81632,6.69218 0.19607,6.907 -6.58875,11.92951 -12.86343,10.71083 -8.21344,-0.99562 -14.24185,-9.85518 -12.49382,-18.25737 1.54211,-10.78621 12.75113,-18.38943 22.89359,-15.65962 11.86257,2.42582 20.00065,15.79672 17.20605,27.99309 -2.41584,13.54418 -15.7679,23.59081 -28.91368,21.59767 -14.20193,-1.45306 -26.32571,-14.644 -26.46485,-29.59643 -0.8484,-17.59211 12.58621,-34.40757 29.59974,-35.87494 17.64776,-2.34404 36.43269,10.56977 40.14043,28.9258 3.86993,15.99133 -2.31691,34.4508 -15.45688,44.18203 -0.10231,3.94543 4.80831,7.62163 7.87431,4.41178 19.69304,-16.79994 22.96064,-50.96148 5.42672,-70.6373 -8.57029,-10.04432 -21.48622,-15.8896 -34.39478,-15.63007 z"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#808080;stroke-width:5.00000048;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;enable-background:accumulate" />
+ <g
+ id="0heart"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:113.93434906px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#808080;stroke-width:4.7127285;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ transform="matrix(1.0677772,0,0,1.0541795,-59.938025,-33.284976)">
+ <path
+ inkscape:connector-curvature="0"
+ id="path2998"
+ d="m 572.55695,170.41572 c 7.52883,8e-5 13.44436,4.35792 17.74661,13.07352 1.55765,3.44925 2.37358,6.0825 2.44781,7.89974 l 0.1669,0 c 1.29802,-6.00819 3.65311,-10.99652 7.06526,-14.96501 4.00544,-4.00542 8.51163,-6.00817 13.51858,-6.00825 7.75131,8e-5 13.96355,4.15393 18.63672,12.46157 1.18672,3.07837 1.78013,5.97123 1.78022,8.67859 -9e-5,9.27205 -3.85724,18.11753 -11.57145,26.53647 l -29.42933,35.32632 -0.3338,0 -31.26518,-38.33045 c -6.2308,-7.603 -9.34619,-15.4471 -9.34618,-23.53234 -10e-6,-7.8255 3.69024,-14.03773 11.07077,-18.63672 3.11537,-1.66888 6.28639,-2.50336 9.51307,-2.50344"
+ style="stroke:#808080;stroke-width:4.7127285;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <path
+ style="fill:#000000;fill-opacity:0.57983195;fill-rule:nonzero;stroke:#000000;stroke-width:2.50000024;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 261.37374,293.86379 c -21.42857,-42.85714 -21.42857,-42.85714 -21.42857,-42.85714 l 40.71428,25 z"
+ id="0cursor"
+ inkscape:connector-curvature="0"
+ inkscape:label="#path3043" />
+ <g
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:40px;line-height:125%;font-family:'Droid Sans';-inkscape-font-specification:'Droid Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="0hard0"
+ inkscape:label="#text5595"
+ transform="matrix(0.7,0,0,0.7,64.765671,18.829203)">
+ <g
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:40px;line-height:125%;font-family:'Droid Sans';-inkscape-font-specification:'Droid Sans, Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="text5638">
+ <path
+ d="m 361.89825,341.57028 q -1.58203,0 -2.63671,1.11328 -1.03516,1.11328 -1.19141,3.4961 l 7.59766,0 q -0.0195,-0.9961 -0.25391,-1.83594 -0.23438,-0.83984 -0.70313,-1.44531 -0.46875,-0.625 -1.17187,-0.97657 -0.70313,-0.35156 -1.64063,-0.35156 z m 0.76172,18.39844 q -2.34375,0 -4.3164,-0.68359 -1.97266,-0.6836 -3.39844,-2.05079 -1.42578,-1.38671 -2.22656,-3.47656 -0.78125,-2.10937 -0.78125,-4.9414 0,-2.8711 0.72265,-5.01954 0.72266,-2.14843 2.01172,-3.57421 1.3086,-1.44532 3.125,-2.16797 1.83594,-0.72266 4.0625,-0.72266 2.16797,0 3.90625,0.66406 1.75781,0.64453 2.96875,1.91407 1.23047,1.26953 1.875,3.125 0.66406,1.83593 0.66406,4.21875 l 0,2.89062 -13.32031,0 q 0.0391,1.25 0.39063,2.26563 0.37109,0.99609 1.01562,1.69921 0.66406,0.6836 1.58203,1.05469 0.9375,0.3711 2.12891,0.3711 0.99609,0 1.875,-0.0977 0.89844,-0.11719 1.73828,-0.33203 0.83984,-0.21485 1.66016,-0.52735 0.82031,-0.33203 1.67968,-0.76171 l 0,4.60937 q -0.78125,0.41016 -1.58203,0.70313 -0.78125,0.27343 -1.66015,0.46875 -0.87891,0.19531 -1.89453,0.27343 -1.01563,0.0977 -2.22657,0.0977 z"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path5643"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 389.02716,359.57809 -1.15234,-2.96875 -0.17578,0 q -0.64454,0.87891 -1.28907,1.52344 -0.64453,0.625 -1.40625,1.03516 -0.76172,0.41015 -1.71875,0.60547 -0.9375,0.19531 -2.1875,0.19531 -1.32812,0 -2.46093,-0.41016 -1.13282,-0.42968 -1.97266,-1.26953 -0.82031,-0.85937 -1.28906,-2.14844 -0.46875,-1.30859 -0.46875,-3.08593 0,-3.47657 2.22656,-5.11719 2.22656,-1.66016 6.66016,-1.83594 l 3.47656,-0.11719 0,-1.64062 q 0,-1.34766 -0.78125,-1.99219 -0.78125,-0.64453 -2.1875,-0.64453 -1.40625,0 -2.75391,0.41016 -1.32812,0.41015 -2.67578,1.09375 l -1.93359,-3.94532 q 1.64062,-0.91796 3.63281,-1.44531 1.99219,-0.52734 4.17969,-0.52734 4.08203,0 6.25,1.91406 2.1875,1.91406 2.1875,5.82031 l 0,14.55078 -4.16016,0 z m -1.75781,-10.11718 -1.97266,0.0781 q -1.1914,0.0391 -2.01172,0.3125 -0.82031,0.27344 -1.32812,0.74219 -0.48828,0.44922 -0.72266,1.09375 -0.21484,0.625 -0.21484,1.40625 0,1.36719 0.66406,1.95312 0.66406,0.56641 1.73828,0.56641 0.82031,0 1.52344,-0.27344 0.70312,-0.29297 1.21094,-0.83984 0.52734,-0.56641 0.82031,-1.36719 0.29297,-0.82031 0.29297,-1.875 l 0,-1.79687 z"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path5645"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 413.87091,353.09372 q 0,1.71875 -0.625,3.00781 -0.625,1.28906 -1.77734,2.14844 -1.15235,0.85937 -2.79297,1.28906 -1.64063,0.42969 -3.67188,0.42969 -1.07422,0 -1.99218,-0.0781 -0.91797,-0.0586 -1.73829,-0.21484 -0.82031,-0.15625 -1.58203,-0.39062 -0.76172,-0.23438 -1.54297,-0.58594 l 0,-4.92188 q 0.82032,0.41016 1.71875,0.74219 0.91797,0.33203 1.81641,0.58594 0.89844,0.23437 1.73828,0.37109 0.85938,0.13672 1.58203,0.13672 0.80078,0 1.36719,-0.13672 0.56641,-0.15625 0.91797,-0.41015 0.37109,-0.27344 0.52734,-0.625 0.17578,-0.3711 0.17578,-0.78125 0,-0.41016 -0.13671,-0.72266 -0.11719,-0.33203 -0.56641,-0.68359 -0.44922,-0.3711 -1.32813,-0.82032 -0.85937,-0.46875 -2.32421,-1.13281 -1.42579,-0.64453 -2.48047,-1.26953 -1.03516,-0.64453 -1.71875,-1.42578 -0.66407,-0.78125 -0.9961,-1.77735 -0.33203,-1.01562 -0.33203,-2.40234 0,-1.52344 0.58594,-2.65625 0.58594,-1.15234 1.66016,-1.91406 1.07421,-0.76172 2.57812,-1.13281 1.52344,-0.39063 3.37891,-0.39063 1.95312,0 3.71093,0.44922 1.75782,0.44922 3.61329,1.34766 l -1.79688,4.21875 q -1.48437,-0.70313 -2.83203,-1.15235 -1.34766,-0.44922 -2.69531,-0.44922 -1.21094,0 -1.75782,0.42969 -0.52734,0.42969 -0.52734,1.17188 0,0.39062 0.13672,0.70312 0.13672,0.29297 0.54687,0.625 0.41016,0.3125 1.15235,0.70313 0.74219,0.37109 1.93359,0.91796 1.38672,0.60547 2.5,1.21094 1.11328,0.58594 1.91406,1.34766 0.80079,0.76172 1.23047,1.77734 0.42969,1.01563 0.42969,2.46094 z"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path5647"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 415.41388,337.74216 6.52344,0 3.51562,12.28515 q 0.3125,1.01563 0.44922,2.16797 0.15625,1.15235 0.19531,2.07031 l 0.11719,0 q 0.0391,-0.44921 0.0977,-0.99609 0.0781,-0.54687 0.17578,-1.11328 0.0977,-0.56641 0.21484,-1.11328 0.13672,-0.56641 0.27344,-1.01563 l 3.4375,-12.28515 6.5625,0 -8.63281,24.6289 q -1.21094,3.45703 -3.30078,5.13672 -2.08985,1.67969 -5.23438,1.67969 -1.01562,0 -1.75781,-0.11719 -0.74219,-0.0977 -1.26953,-0.21484 l 0,-4.72656 q 0.41015,0.0977 1.03515,0.17578 0.625,0.0781 1.3086,0.0781 0.9375,0 1.60156,-0.2539 0.66406,-0.25391 1.13281,-0.72266 0.48828,-0.44922 0.82031,-1.09375 0.35157,-0.64453 0.60547,-1.44531 l 0.3711,-1.09375 -8.24219,-22.03125 z"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path5649"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ <g
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:40px;line-height:125%;font-family:'Droid Sans';-inkscape-font-specification:'Droid Sans, Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="0hard1"
+ inkscape:label="#text5599"
+ transform="matrix(0.7,0,0,0.7,55.673321,14.516296)">
+ <path
+ d="m 372.53442,411.00665 -5.95703,0 0,-12.7539 q 0,-2.36328 -0.70312,-3.53516 -0.70313,-1.19141 -2.20703,-1.19141 -1.13282,0 -1.89453,0.46875 -0.74219,0.46875 -1.19141,1.38672 -0.44922,0.91797 -0.64453,2.26563 -0.19531,1.34765 -0.19531,3.08594 l 0,10.27343 -5.95704,0 0,-21.83593 4.55079,0 0.80078,2.79296 0.33203,0 q 0.46875,-0.83984 1.11328,-1.44531 0.66406,-0.60547 1.44531,-0.99609 0.78125,-0.39063 1.66016,-0.56641 0.8789,-0.19531 1.77734,-0.19531 2.2461,0 3.8086,0.78125 1.58203,0.76172 2.42187,2.42187 l 0.48828,0 q 0.46875,-0.83984 1.13281,-1.44531 0.66407,-0.60547 1.46485,-0.99609 0.80078,-0.39063 1.67969,-0.56641 0.89843,-0.19531 1.79687,-0.19531 3.51563,0 5.29297,1.91406 1.79687,1.89453 1.79687,6.09375 l 0,14.23828 -5.97656,0 0,-12.7539 q 0,-2.36328 -0.70312,-3.53516 -0.70313,-1.19141 -2.20703,-1.19141 -2.12891,0 -3.02735,1.69922 -0.89844,1.67969 -0.89844,4.82422 l 0,10.95703 z"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path5626"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 400.2688,392.99884 q -1.58203,0 -2.63672,1.11328 -1.03516,1.11328 -1.19141,3.4961 l 7.59766,0 q -0.0195,-0.9961 -0.25391,-1.83594 -0.23437,-0.83985 -0.70312,-1.44531 -0.46875,-0.625 -1.17188,-0.97657 -0.70312,-0.35156 -1.64062,-0.35156 z m 0.76172,18.39844 q -2.34375,0 -4.31641,-0.6836 -1.97265,-0.68359 -3.39844,-2.05078 -1.42578,-1.38672 -2.22656,-3.47656 -0.78125,-2.10937 -0.78125,-4.94141 0,-2.87109 0.72266,-5.01953 0.72265,-2.14843 2.01172,-3.57422 1.30859,-1.44531 3.125,-2.16796 1.83593,-0.72266 4.0625,-0.72266 2.16797,0 3.90625,0.66406 1.75781,0.64453 2.96875,1.91406 1.23047,1.26954 1.875,3.125 0.66406,1.83594 0.66406,4.21875 l 0,2.89063 -13.32031,0 q 0.0391,1.25 0.39062,2.26562 0.3711,0.9961 1.01563,1.69922 0.66406,0.6836 1.58203,1.05469 0.9375,0.37109 2.1289,0.37109 0.9961,0 1.875,-0.0976 0.89844,-0.11719 1.73829,-0.33203 0.83984,-0.21485 1.66015,-0.52735 0.82031,-0.33203 1.67969,-0.76172 l 0,4.60938 q -0.78125,0.41016 -1.58203,0.70312 -0.78125,0.27344 -1.66016,0.46875 -0.8789,0.19532 -1.89453,0.27344 -1.01562,0.0977 -2.22656,0.0977 z"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path5628"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 421.14771,411.39728 q -1.67969,0 -3.06641,-0.72266 -1.38672,-0.72265 -2.38281,-2.1289 -0.9961,-1.42579 -1.5625,-3.53516 -0.54688,-2.10938 -0.54688,-4.88281 0,-2.8125 0.54688,-4.92188 0.5664,-2.1289 1.58203,-3.55469 1.03515,-1.44531 2.46094,-2.16796 1.42578,-0.72266 3.14453,-0.72266 1.05468,0 1.93359,0.25391 0.87891,0.23437 1.58203,0.68359 0.70313,0.42969 1.25,1.01562 0.56641,0.56641 0.9961,1.25 l 0.19531,0 q -0.11719,-0.76171 -0.21485,-1.54296 -0.0976,-0.66407 -0.17578,-1.40625 -0.0586,-0.76172 -0.0586,-1.40625 l 0,-6.99219 5.95703,0 0,30.39062 -4.55078,0 -1.15234,-2.83203 -0.25391,0 q -0.41016,0.66406 -0.9375,1.26953 -0.52734,0.58594 -1.23047,1.01563 -0.68359,0.42969 -1.5625,0.68359 -0.85937,0.25391 -1.95312,0.25391 z m 2.16796,-4.7461 q 1.05469,0 1.79688,-0.35156 0.74219,-0.37109 1.19141,-1.09375 0.46875,-0.74219 0.68359,-1.83594 0.23437,-1.09375 0.25391,-2.55859 l 0,-0.64453 q 0,-1.58203 -0.19532,-2.8125 -0.19531,-1.23047 -0.64453,-2.05078 -0.44922,-0.83985 -1.21094,-1.26953 -0.76171,-0.42969 -1.91406,-0.42969 -1.875,0 -2.7539,1.69922 -0.87891,1.67969 -0.87891,4.90234 0,3.22266 0.87891,4.84375 0.89843,1.60156 2.79296,1.60156 z"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path5630"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 438.76489,383.52618 q 0,-0.83984 0.25391,-1.38671 0.25391,-0.56641 0.68359,-0.89844 0.44922,-0.35156 1.03516,-0.48828 0.60547,-0.13672 1.26953,-0.13672 0.66406,0 1.25,0.13672 0.58594,0.13672 1.01563,0.48828 0.44921,0.33203 0.70312,0.89844 0.27344,0.54687 0.27344,1.38671 0,0.82032 -0.27344,1.38672 -0.25391,0.56641 -0.70312,0.91797 -0.42969,0.33203 -1.01563,0.48828 -0.58594,0.13672 -1.25,0.13672 -0.66406,0 -1.26953,-0.13672 -0.58594,-0.15625 -1.03516,-0.48828 -0.42968,-0.35156 -0.68359,-0.91797 -0.25391,-0.5664 -0.25391,-1.38672 z m 6.21094,27.48047 -5.95703,0 0,-21.83593 5.95703,0 0,21.83593 z"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path5632"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 465.48364,411.00665 -0.80078,-2.79297 -0.3125,0 q -0.48828,0.83985 -1.17187,1.44532 -0.66407,0.58593 -1.46485,0.97656 -0.80078,0.39062 -1.69922,0.56641 -0.89843,0.19531 -1.83593,0.19531 -1.60157,0 -2.91016,-0.44922 -1.30859,-0.46875 -2.24609,-1.44531 -0.9375,-0.97657 -1.44532,-2.48047 -0.50781,-1.50391 -0.50781,-3.61328 l 0,-14.23828 5.95703,0 0,12.7539 q 0,2.36328 0.70313,3.55469 0.72265,1.17187 2.28515,1.17187 1.17188,0 1.95313,-0.46875 0.78125,-0.46875 1.23047,-1.38671 0.46875,-0.91797 0.66406,-2.26563 0.19531,-1.34766 0.19531,-3.08594 l 0,-10.27343 5.95703,0 0,21.83593 -4.55078,0 z"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path5634"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 495.03442,411.00665 -5.95703,0 0,-12.7539 q 0,-2.36328 -0.70312,-3.53516 -0.70313,-1.19141 -2.20703,-1.19141 -1.13282,0 -1.89453,0.46875 -0.74219,0.46875 -1.19141,1.38672 -0.44922,0.91797 -0.64453,2.26563 -0.19531,1.34765 -0.19531,3.08594 l 0,10.27343 -5.95704,0 0,-21.83593 4.55079,0 0.80078,2.79296 0.33203,0 q 0.46875,-0.83984 1.11328,-1.44531 0.66406,-0.60547 1.44531,-0.99609 0.78125,-0.39063 1.66016,-0.56641 0.8789,-0.19531 1.77734,-0.19531 2.2461,0 3.8086,0.78125 1.58203,0.76172 2.42187,2.42187 l 0.48828,0 q 0.46875,-0.83984 1.13281,-1.44531 0.66407,-0.60547 1.46485,-0.99609 0.80078,-0.39063 1.67969,-0.56641 0.89843,-0.19531 1.79687,-0.19531 3.51563,0 5.29297,1.91406 1.79687,1.89453 1.79687,6.09375 l 0,14.23828 -5.97656,0 0,-12.7539 q 0,-2.36328 -0.70312,-3.53516 -0.70313,-1.19141 -2.20703,-1.19141 -2.12891,0 -3.02735,1.69922 -0.89844,1.67969 -0.89844,4.82422 l 0,10.95703 z"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path5636"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:40px;line-height:125%;font-family:'Droid Sans';-inkscape-font-specification:'Droid Sans, Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="0hard2"
+ inkscape:label="#text5603"
+ transform="matrix(0.7,0,0,0.7,55.939641,18.659146)">
+ <path
+ d="m 375.58685,458.14954 -5.95703,0 0,-12.75391 q 0,-2.36328 -0.74219,-3.53516 -0.72265,-1.1914 -2.24609,-1.1914 -1.15234,0 -1.93359,0.46875 -0.78125,0.46875 -1.25,1.38672 -0.46875,0.91796 -0.66407,2.26562 -0.19531,1.34766 -0.19531,3.08594 l 0,10.27344 -5.95703,0 0,-30.39063 5.95703,0 0,6.19141 q 0,0.82031 -0.0391,1.73828 -0.0391,0.89844 -0.0977,1.66015 -0.0781,0.89844 -0.13672,1.75782 l 0.3125,0 q 0.95704,-1.69922 2.44141,-2.44141 1.48438,-0.76172 3.35938,-0.76172 1.62109,0 2.92968,0.46875 1.32813,0.44922 2.26563,1.42578 0.9375,0.97657 1.44531,2.5 0.50781,1.50391 0.50781,3.61328 l 0,14.23829 z"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path5652"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 394.39545,458.14954 -1.15235,-2.96875 -0.17578,0 q -0.64453,0.8789 -1.28906,1.52343 -0.64453,0.625 -1.40625,1.03516 -0.76172,0.41016 -1.71875,0.60547 -0.9375,0.19531 -2.1875,0.19531 -1.32813,0 -2.46094,-0.41016 -1.13281,-0.42968 -1.97265,-1.26953 -0.82032,-0.85937 -1.28907,-2.14843 -0.46875,-1.3086 -0.46875,-3.08594 0,-3.47656 2.22657,-5.11719 2.22656,-1.66016 6.66015,-1.83594 l 3.47656,-0.11718 0,-1.64063 q 0,-1.34766 -0.78125,-1.99219 -0.78125,-0.64453 -2.1875,-0.64453 -1.40625,0 -2.7539,0.41016 -1.32813,0.41015 -2.67578,1.09375 l -1.9336,-3.94531 q 1.64063,-0.91797 3.63282,-1.44532 1.99218,-0.52734 4.17968,-0.52734 4.08203,0 6.25,1.91406 2.1875,1.91406 2.1875,5.82031 l 0,14.55079 -4.16015,0 z m -1.75782,-10.11719 -1.97265,0.0781 q -1.19141,0.0391 -2.01172,0.3125 -0.82031,0.27344 -1.32813,0.74219 -0.48828,0.44922 -0.72265,1.09375 -0.21485,0.625 -0.21485,1.40625 0,1.36719 0.66407,1.95313 0.66406,0.5664 1.73828,0.5664 0.82031,0 1.52344,-0.27344 0.70312,-0.29296 1.21093,-0.83984 0.52735,-0.56641 0.82032,-1.36719 0.29296,-0.82031 0.29296,-1.875 l 0,-1.79687 z"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path5654"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 416.07513,435.90344 q 0.23438,0 0.50782,0.0195 0.29297,0 0.54687,0.0391 0.27344,0.0195 0.48828,0.0586 0.23438,0.0195 0.35157,0.0586 l 0,5.58594 q -0.15625,-0.0391 -0.42969,-0.0781 -0.27344,-0.0391 -0.58594,-0.0586 -0.29297,-0.0391 -0.58594,-0.0391 -0.29297,-0.0195 -0.48828,-0.0195 -1.15234,0 -2.1289,0.29297 -0.95704,0.29297 -1.66016,0.95703 -0.68359,0.64453 -1.07422,1.71875 -0.37109,1.05469 -0.37109,2.59765 l 0,11.11329 -5.95703,0 0,-21.83594 4.51171,0 0.87891,3.28125 0.29297,0 q 0.46875,-0.83985 1.01562,-1.52344 0.54688,-0.68359 1.21094,-1.15234 0.6836,-0.48828 1.52344,-0.74219 0.85937,-0.27344 1.95312,-0.27344 z"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path5656"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 428.45795,458.54016 q -1.67969,0 -3.06641,-0.72266 -1.38672,-0.72265 -2.38281,-2.1289 -0.9961,-1.42578 -1.5625,-3.53516 -0.54688,-2.10937 -0.54688,-4.88281 0,-2.8125 0.54688,-4.92188 0.5664,-2.1289 1.58203,-3.55468 1.03516,-1.44532 2.46094,-2.16797 1.42578,-0.72266 3.14453,-0.72266 1.05469,0 1.93359,0.25391 0.87891,0.23437 1.58203,0.68359 0.70313,0.42969 1.25,1.01563 0.56641,0.5664 0.9961,1.25 l 0.19531,0 q -0.11719,-0.76172 -0.21484,-1.54297 -0.0977,-0.66406 -0.17579,-1.40625 -0.0586,-0.76172 -0.0586,-1.40625 l 0,-6.99219 5.95703,0 0,30.39063 -4.55078,0 -1.15234,-2.83204 -0.25391,0 q -0.41016,0.66407 -0.9375,1.26954 -0.52734,0.58593 -1.23047,1.01562 -0.68359,0.42969 -1.5625,0.68359 -0.85937,0.25391 -1.95312,0.25391 z m 2.16797,-4.74609 q 1.05468,0 1.79687,-0.35157 0.74219,-0.37109 1.19141,-1.09375 0.46875,-0.74218 0.68359,-1.83593 0.23438,-1.09375 0.25391,-2.5586 l 0,-0.64453 q 0,-1.58203 -0.19532,-2.8125 -0.19531,-1.23047 -0.64453,-2.05078 -0.44922,-0.83984 -1.21093,-1.26953 -0.76172,-0.42969 -1.91407,-0.42969 -1.875,0 -2.7539,1.69922 -0.87891,1.67969 -0.87891,4.90234 0,3.22266 0.87891,4.84375 0.89843,1.60157 2.79297,1.60157 z"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path5658"
+ inkscape:connector-curvature="0" />
+ </g>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:151.59999084px;line-height:125%;font-family:'Droid Sans';-inkscape-font-specification:'Droid Sans, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ff0000;fill-opacity:1;stroke:#550000;stroke-width:2.50000022;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;"
+ x="105.09922"
+ y="363.60458"
+ id="0error"
+ sodipodi:linespacing="125%"
+ transform="scale(1.0032264,0.99678398)"
+ inkscape:label="#text3394"><tspan
+ sodipodi:role="line"
+ id="tspan3396"
+ x="105.09922"
+ y="363.60458">✘</tspan></text>
+ <path
+ inkscape:connector-curvature="0"
+ id="0n0"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:27.5px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.75000016;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 404.02266,260.24844 q 0,-3.75976 -0.71167,-5.29052 -0.69825,-1.54419 -2.36328,-1.54419 -1.66504,0 -2.37671,1.54419 -0.71167,1.53076 -0.71167,5.29052 0,3.80005 0.71167,5.35767 0.71167,1.55762 2.37671,1.55762 1.65161,0 2.36328,-1.55762 0.71167,-1.55762 0.71167,-5.35767 z m 5.16967,0.0403 q 0,4.98169 -2.14843,7.69409 -2.14844,2.69897 -6.09619,2.69897 -3.96119,0 -6.10962,-2.69897 -2.14844,-2.7124 -2.14844,-7.69409 0,-4.99512 2.14844,-7.69409 2.14843,-2.71241 6.10962,-2.71241 3.94775,0 6.09619,2.71241 2.14843,2.69897 2.14843,7.69409 z"
+ inkscape:label="#path4209" />
+ <path
+ inkscape:connector-curvature="0"
+ id="0n1"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:27.5px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.75000016;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 415.63426,266.72061 4.56543,0 0,-12.95776 -4.68628,0.96679 0,-3.51806 4.65942,-0.9668 4.91456,0 0,16.47583 4.56543,0 0,3.57178 -14.01856,0 0,-3.57178 z"
+ inkscape:label="#path4211" />
+ <path
+ inkscape:connector-curvature="0"
+ id="0n2"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:27.5px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.75000016;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 442.68776,266.49234 8.82202,0 0,3.80005 -14.56909,0 0,-3.80005 7.31812,-6.45874 q 0.98022,-0.88623 1.45019,-1.73218 0.46997,-0.84595 0.46997,-1.75903 0,-1.40991 -0.95337,-2.26929 -0.93994,-0.85937 -2.51098,-0.85937 -1.2085,0 -2.64527,0.52368 -1.43676,0.51025 -3.07495,1.53076 l 0,-4.4043 q 1.74561,-0.57739 3.45093,-0.8728 1.70532,-0.30884 3.34351,-0.30884 3.59863,0 5.58593,1.58448 2.00074,1.58447 2.00074,4.41772 0,1.63818 -0.84595,3.06152 -0.84595,1.40992 -3.55835,3.78662 l -4.28345,3.75977 z"
+ inkscape:label="#path4213" />
+ <path
+ inkscape:connector-curvature="0"
+ id="0n3"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:27.5px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.75000016;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 469.28474,259.48306 q 2.02759,0.52368 3.07495,1.82617 1.06079,1.28907 1.06079,3.2898 0,2.98096 -2.28271,4.53857 -2.28272,1.54419 -6.66016,1.54419 -1.54419,0 -3.10181,-0.25512 -1.54418,-0.2417 -3.06152,-0.73853 l 0,-3.98804 q 1.4502,0.7251 2.87354,1.10108 1.43676,0.36255 2.81982,0.36255 2.05444,0 3.14209,-0.71167 1.10107,-0.71167 1.10107,-2.04102 0,-1.36963 -1.12792,-2.06787 -1.11451,-0.71167 -3.30323,-0.71167 l -2.06787,0 0,-3.33008 2.17529,0 q 1.94703,0 2.90039,-0.60425 0.95337,-0.61767 0.95337,-1.86645 0,-1.15479 -0.92651,-1.78589 -0.92651,-0.6311 -2.61841,-0.6311 -1.24878,0 -2.52441,0.28198 -1.27564,0.28198 -2.53784,0.83252 l 0,-3.78662 q 1.53076,-0.42969 3.03466,-0.64453 1.50391,-0.21485 2.95411,-0.21485 3.90747,0 5.84106,1.28907 1.94702,1.27563 1.94702,3.85375 0,1.75904 -0.92651,2.88697 -0.92652,1.1145 -2.73926,1.57104 z"
+ inkscape:label="#path4215" />
+ <path
+ inkscape:connector-curvature="0"
+ id="0n4"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:27.5px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.75000016;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 488.08015,254.50137 -5.66651,8.39234 5.66651,0 0,-8.39234 z m -0.85938,-4.25659 5.74707,0 0,12.64893 2.86011,0 0,3.74634 -2.86011,0 0,3.65234 -4.88769,0 0,-3.65234 -8.88916,0 0,-4.43116 8.02978,-11.96411 z"
+ inkscape:label="#path4217" />
+ <path
+ inkscape:connector-curvature="0"
+ id="0n5"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:27.5px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.75000016;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 502.39748,250.24478 12.85034,0 0,3.80005 -8.72803,0 0,3.10181 q 0.59082,-0.16114 1.18164,-0.2417 0.60425,-0.094 1.24878,-0.094 3.66577,0 5.70679,1.8396 2.04101,1.82618 2.04101,5.10254 0,3.24951 -2.229,5.08911 -2.21558,1.8396 -6.16333,1.8396 -1.70532,0 -3.38379,-0.33569 -1.66504,-0.32227 -3.31665,-0.99365 l 0,-4.06861 q 1.63818,0.93995 3.10181,1.40992 1.47705,0.46997 2.77954,0.46997 1.87988,0 2.9541,-0.91309 1.08765,-0.92651 1.08765,-2.49756 0,-1.58447 -1.08765,-2.49756 -1.07422,-0.91308 -2.9541,-0.91308 -1.1145,0 -2.37671,0.29541 -1.26221,0.28198 -2.7124,0.88623 l 0,-11.2793 z"
+ inkscape:label="#path4219" />
+ <path
+ inkscape:connector-curvature="0"
+ id="0n6"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:27.5px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.75000016;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 531.06232,260.39615 q -1.3562,0 -2.04101,0.88623 -0.67139,0.8728 -0.67139,2.63184 0,1.75903 0.67139,2.64526 0.68481,0.8728 2.04101,0.8728 1.36963,0 2.04102,-0.8728 0.68481,-0.88623 0.68481,-2.64526 0,-1.75904 -0.68481,-2.63184 -0.67139,-0.88623 -2.04102,-0.88623 z m 6.39161,-9.62769 0,3.70606 q -1.27564,-0.60425 -2.40357,-0.88623 -1.12793,-0.29541 -2.20215,-0.29541 -2.30957,0 -3.59863,1.28906 -1.28906,1.27563 -1.50391,3.80005 0.88623,-0.65796 1.92017,-0.98023 1.03394,-0.33569 2.25586,-0.33569 3.07495,0 4.95483,1.79932 1.89331,1.79931 1.89331,4.71313 0,3.22266 -2.10815,5.16968 -2.10815,1.93359 -5.65308,1.93359 -3.90747,0 -6.0559,-2.63183 -2.13501,-2.64527 -2.13501,-7.49268 0,-4.96826 2.49755,-7.80151 2.51099,-2.84668 6.875,-2.84668 1.38306,0 2.68555,0.21484 1.30249,0.21485 2.57813,0.64453 z"
+ inkscape:label="#path4221" />
+ <path
+ inkscape:connector-curvature="0"
+ id="0n7"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:27.5px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.75000016;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 544.88277,250.24478 15.1062,0 0,2.91382 -7.81494,17.13379 -5.0354,0 7.39868,-16.24756 -9.65454,0 0,-3.80005 z"
+ inkscape:label="#path4223" />
+ <path
+ inkscape:connector-curvature="0"
+ id="0n8"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:27.5px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.75000016;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 574.0981,261.32266 q -1.4502,0 -2.22901,0.79224 -0.77881,0.79224 -0.77881,2.26929 0,1.47705 0.77881,2.26928 0.77881,0.77881 2.22901,0.77881 1.43676,0 2.20214,-0.77881 0.76538,-0.79223 0.76538,-2.26928 0,-1.49048 -0.76538,-2.26929 -0.76538,-0.79224 -2.20214,-0.79224 z m -3.7732,-1.70532 q -1.82617,-0.55054 -2.75268,-1.69189 -0.92652,-1.14136 -0.92652,-2.84668 0,-2.53785 1.89331,-3.86719 1.89331,-1.32935 5.55909,-1.32935 3.63891,0 5.53222,1.32935 1.89331,1.31592 1.89331,3.86719 0,1.70532 -0.93994,2.84668 -0.92651,1.14135 -2.75268,1.69189 2.04101,0.56396 3.07495,1.8396 1.04736,1.26221 1.04736,3.1958 0,2.98096 -1.9873,4.51172 -1.97388,1.51733 -5.86792,1.51733 -3.90748,0 -5.90821,-1.51733 -1.9873,-1.53076 -1.9873,-4.51172 0,-1.93359 1.03393,-3.1958 1.04737,-1.27564 3.08838,-1.8396 z m 1.2085,-4.01489 q 0,1.19507 0.65796,1.8396 0.67138,0.64453 1.90674,0.64453 1.20849,0 1.86645,-0.64453 0.65796,-0.64453 0.65796,-1.8396 0,-1.19507 -0.65796,-1.82617 -0.65796,-0.64454 -1.86645,-0.64454 -1.23536,0 -1.90674,0.64454 -0.65796,0.64453 -0.65796,1.82617 z"
+ inkscape:label="#path4225" />
+ <path
+ inkscape:connector-curvature="0"
+ id="0n9"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:27.5px;line-height:125%;font-family:Sans;-inkscape-font-specification:'Sans, Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.75000016;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 589.0734,269.84927 0,-3.70605 q 1.23535,0.57739 2.36328,0.8728 1.12793,0.28198 2.229,0.28198 2.30958,0 3.59864,-1.27563 1.28906,-1.28906 1.51733,-3.81348 -0.91308,0.67139 -1.94702,1.00708 -1.03394,0.3357 -2.24243,0.3357 -3.07495,0 -4.96826,-1.78589 -1.87989,-1.79932 -1.87989,-4.72656 0,-3.23609 2.09473,-5.18311 2.10815,-1.94702 5.63965,-1.94702 3.9209,0 6.06934,2.64526 2.14843,2.64527 2.14843,7.47925 0,4.96826 -2.51098,7.81494 -2.51099,2.83325 -6.88843,2.83325 -1.40991,0 -2.69898,-0.21484 -1.28906,-0.20142 -2.52441,-0.61768 z m 6.37817,-9.65454 q 1.3562,0 2.04102,-0.8728 0.68481,-0.88623 0.68481,-2.64526 0,-1.74561 -0.68481,-2.63184 -0.68482,-0.88623 -2.04102,-0.88623 -1.3562,0 -2.04101,0.88623 -0.68482,0.88623 -0.68482,2.63184 0,1.75903 0.68482,2.64526 0.68481,0.8728 2.04101,0.8728 z"
+ inkscape:label="#path4227" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:31.96330261px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.75000012;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ x="274.35486"
+ y="-433.2915"
+ id="0reload"
+ sodipodi:linespacing="125%"
+ inkscape:label="#text4239"
+ transform="matrix(-0.00170809,1.0146722,-0.98553716,-0.00165905,0,0)"><tspan
+ sodipodi:role="line"
+ id="tspan4241"
+ x="274.35486"
+ y="-433.2915"
+ style="stroke-width:1.75000012;stroke-miterlimit:4;stroke-dasharray:none">↻</tspan></text>
+ </g>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="43.642509mm"
+ height="44.651615mm"
+ viewBox="0 0 154.63881 158.21438"
+ id="svg6343"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="icon.svg">
+ <defs
+ id="defs6345" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.1542002"
+ inkscape:cx="-80.961712"
+ inkscape:cy="22.846199"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1920"
+ inkscape:window-height="1136"
+ inkscape:window-x="1600"
+ inkscape:window-y="27"
+ inkscape:window-maximized="1"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <metadata
+ id="metadata6348">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-113.70362,-86.112208)">
+ <g
+ transform="translate(9.99238,-85.305267)"
+ style="fill:#ff41ff;fill-opacity:1;stroke:#803980;stroke-width:5.00000048;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ inkscape:label="#g3356"
+ id="0cross">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#ff41ff;fill-opacity:1;stroke:#803980;stroke-width:5;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 42.5625,125.5 0,31.25 -31.25,0 0,25 31.25,0 0,31.25 25,0 0,-31.25 31.25,0 0,-25 -31.25,0 0,-31.25 -25,0 z"
+ transform="translate(114.94512,48.417475)"
+ id="rect3352" />
+ </g>
+ <path
+ transform="matrix(1.138458,0.01858784,-0.01944847,1.1911688,-359.02128,61.200173)"
+ inkscape:label="#path3348"
+ inkscape:transform-center-y="-4.0794014"
+ inkscape:transform-center-x="0.47783259"
+ d="m 536.391,131.10309 -47.49475,0.72114 -15.36253,-44.947336 38.00017,-28.500132 38.84794,27.33329 z"
+ inkscape:randomized="0"
+ inkscape:rounded="0"
+ inkscape:flatsided="true"
+ sodipodi:arg2="1.5556138"
+ sodipodi:arg1="0.92729522"
+ sodipodi:r2="32.545895"
+ sodipodi:r1="40.406101"
+ sodipodi:cy="98.778206"
+ sodipodi:cx="512.14734"
+ sodipodi:sides="5"
+ id="0penta"
+ style="fill:#00ffff;fill-opacity:1;stroke:#3a8080;stroke-width:4.2930603;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ sodipodi:type="star" />
+ <path
+ inkscape:label="#path3356"
+ inkscape:connector-curvature="0"
+ id="0spiral"
+ d="m 157.88015,154.33473 c -20.15895,-0.32141 -38.9065,16.76425 -41.19858,37.60291 -3.86937,23.35281 16.7358,47.48676 39.64103,45.31644 12.20102,-0.76865 23.76919,-8.45705 29.03604,-20.00332 6.61043,-13.59525 3.19101,-31.78746 -8.72849,-41.00231 -11.91023,-9.84408 -31.5447,-7.79332 -40.34686,5.46911 -8.25602,11.53909 -5.3078,30.58816 7.47626,37.21364 10.28179,6.05468 25.63854,1.15001 29.0991,-11.11553 3.04684,-9.25632 -2.65279,-21.09349 -12.45674,-22.21563 -7.74971,-1.31975 -16.07358,6.63167 -13.65087,14.90034 1.37551,7.39459 14.12722,8.17257 14.08847,-0.22482 -0.0955,-2.72794 -2.63922,-5.69968 -5.32908,-4.79848 4.38499,-3.96292 10.36557,1.52768 9.81632,6.69218 0.19607,6.907 -6.58875,11.92951 -12.86343,10.71083 -8.21344,-0.99562 -14.24185,-9.85518 -12.49382,-18.25737 1.54211,-10.78621 12.75113,-18.38943 22.89359,-15.65962 11.86257,2.42582 20.00065,15.79672 17.20605,27.99309 -2.41584,13.54418 -15.7679,23.59081 -28.91368,21.59767 -14.20193,-1.45306 -26.32571,-14.644 -26.46485,-29.59643 -0.8484,-17.59211 12.58621,-34.40757 29.59974,-35.87494 17.64776,-2.34404 36.43269,10.56977 40.14043,28.9258 3.86993,15.99133 -2.31691,34.4508 -15.45688,44.18203 -0.10231,3.94543 4.80831,7.62163 7.87431,4.41178 19.69304,-16.79994 22.96064,-50.96148 5.42672,-70.6373 -8.57029,-10.04432 -21.48622,-15.8896 -34.39478,-15.63007 z"
+ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;display:inline;overflow:visible;visibility:visible;fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#808036;stroke-width:5.00000048;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;enable-background:accumulate" />
+ </g>
+</svg>
--- /dev/null
+Categories:Nit,Games
+License:Apache2
+Web Site:http://nitlanguage.org
+Source Code:http://nitlanguage.org/nit.git/tree/HEAD:/contrib/memory
+Issue Tracker:https://github.com/nitlang/nit/issues
+
+Summary:memory-based game using shapes and colors
+Description:
+A memory-based game where figures are cliqued in sequence by the computer and should be replayed by the player in the same order.
+As the player progresses, more figures are added and the sequences to remember become longer.
+
+The player can make up to 2 errors to solve a single level.
+At the 3rd error, the level has to be replayed.
+
+The game use a very simple user interface and features big figures with bright colors and simple distinguishable shapes; that makes it suitable for young children.
+.
--- /dev/null
+[package]
+name=memory
+tags=game
+maintainer=Jean Privat <jean@pryen.org>
+license=Apache-2.0
+[upstream]
+browse=https://github.com/nitlang/nit/tree/master/contrib/memory/
+git=https://github.com/nitlang/nit.git
+git.directory=contrib/memory/
+homepage=http://nitlanguage.org
+issues=https://github.com/nitlang/nit/issues
+apk=http://nitlanguage.org/fdroid/apk/memory.apk
--- /dev/null
+# This file is part of NIT (http://www.nitlanguage.org).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# A game of memory using shapes and colors
+#
+# # Features and TODO
+#
+# * [X] Various shapes, colors and sounds
+# * [X] 3 difficulty modes
+# * [X] Saved high scores
+# * [ ] Level selection
+#
+# The remaining issues are
+#
+# * Crappy event system
+# * Crappy UI element placement
+module memory is
+ app_name("Memorize Shapes and Colors")
+ app_namespace "org.nitlanguage.memory"
+ app_version(0, 1, git_revision)
+end
+
+import mnit
+import app::audio
+import mnit::opengles1
+import app::data_store
+
+import drawing
+
+# A figure to click on
+class Button
+ # The place, starting from 0.
+ # Will be used to derive the display place.
+ var place: Int
+
+ # The color of the figure
+ var color: Color
+
+ # The shape of the figure
+ var shape: Image
+
+ # The sound of the figure
+ var sound: Sound
+
+ # x-coordinate on the display
+ var x: Float = 0.0
+ # y-coordinate on the display
+ var y: Float = 0.0
+ # width on the display
+ var w: Float = 0.0
+ # height the display
+ var h: Float = 0.0
+
+ # Event time to live (from 1.0 downto 0.0)
+ var ttl: Float = 0.0
+
+ # Is there a big error on the button?
+ var error = false
+
+ # The initial position (according to shuffle)
+ var from: Pos is noinit
+
+ # The current path if shuffling
+ var path: nullable BPath = null
+
+ # The second path if hard shuffling
+ var path2: nullable BPath = null
+
+ # Is there an hard shuffling?
+ var hard = false
+
+ # The optional text on the button (in the menu)
+ var text: nullable Image = null
+
+ # The color of the text
+ var text_color: nullable Color = null
+
+ # The high score on the menu button
+ var text_max: Int = 0
+
+ # Draw on the display
+ fun blit_on(display: Display)
+ do
+ if ttl > 0.0 then
+ ttl -= 0.1
+ if ttl <= 0.0 then
+ ttl = 0.0
+ path = path2
+ path2 = null
+ if path != null then ttl = path.duration
+ error = false
+ end
+ end
+
+ var x = self.x
+ var y = self.y
+ var p = 0.0
+ if ttl > 0.0 then
+ if path != null then
+ var pos = to_pos
+ path.update(pos, ttl)
+ x = pos.x
+ y = pos.y
+ if hard then
+ p = ttl/5.0
+ if path2 != null then
+ p = 1.0 - p
+ end
+ end
+ else if error then
+ # nothing
+ else
+ y -= ttl * h / 10.0
+ end
+ end
+
+ if not app.player then
+ p = 0.2.lerp(p, 1.0)
+ end
+
+ color.set(display, p)
+ display.blit_centered(shape, x, y)
+ var text = self.text
+ if text != null then
+ text.scale = shape.scale
+ text_color.set(display, p)
+ display.blit_centered(text, x, y - h/8.0)
+ if text_max > 0 then
+ app.blit_number(text_max, app.scale, x, y + h/8.0)
+ end
+ end
+ if display isa Opengles1Display then
+ display.reset_color
+ end
+ if error then
+ app.drawing.error.scale = app.scale
+ display.blit_centered(app.drawing.error, x, y)
+ end
+ end
+
+ redef fun to_s do
+ return "{place},{color},{shape},{sound}"
+ end
+
+ # Check collision
+ fun has(x,y: Float): Bool
+ do
+ return (self.x - x).abs*2.0 <= w and (self.y - y).abs*2.0 <= h
+ end
+
+ # Return a new pos centered on the button
+ fun to_pos: Pos do return new Pos(x, y)
+end
+
+# A rbg color
+class Color
+ # red (from 0.0 to 1.0)
+ var r: Float
+ # green (from 0.0 to 1.0)
+ var g: Float
+ # blue (from 0.0 to 1.0)
+ var b: Float
+
+ # Globally change the color of the display.
+ # The color will be used for the next blit operations.
+ # The color of the display has to be reseted manually (see `Opengles1Display::reset_color`).
+ fun set(display: Display, p: Float)
+ do
+ if display isa Opengles1Display then
+ display.color(p.lerp(r,1.0),p.lerp(g,1.0),p.lerp(b,1.0),p.lerp(1.0,0.0))
+ end
+ end
+end
+
+# A point in the display coordinates
+class Pos
+ # x coordinate
+ var x: Float
+ # y coordinate
+ var y: Float
+ redef fun to_s do return "({x},{y})"
+end
+
+# A cubic Bézier path between two points with two handles.
+class BPath
+ # The origin point
+ var from: Pos
+ # The handle of the origin point
+ var from_handle: Pos
+ # The handle of the destination point
+ var to_handle: Pos
+ # The destination point
+ var to: Pos
+ # The duration on the path
+ var duration: Float
+
+ # Update the coordinates of `cursor` for an absolute time to destination `ttd`
+ fun update(cursor: Pos, ttd: Float)
+ do
+ var p = 1.0 - ttd / duration
+ if p <= 0.0 then
+ cursor.x = from.x
+ cursor.y = from.y
+ return
+ end
+ if p >= 1.1 then
+ cursor.x = to.x
+ cursor.y = to.y
+ end
+ var bx = p.cerp(from.x, from_handle.x, to_handle.x, to.x)
+ var by = p.cerp(from.y, from_handle.y, to_handle.y, to.y)
+ cursor.x = bx
+ cursor.y = by
+ end
+end
+
+redef class App
+
+ # # Assets and resources
+
+ # All the images assets
+ var drawing = new DrawingImages
+
+ # Array of all available colors for the figures
+ var colors = new Array[Color]
+
+ # Array of all available shapes for the figures
+ var shapes = new Array[Image]
+
+ # Array of all available sounds for the figures
+ var sounds = new Array[Sound]
+
+ # The sound to play on error (error)
+ var snd_penalty: Sound is noautoinit
+
+ # The sound of other ui element
+ var snd_click: Sound is noautoinit
+
+ redef fun on_create
+ do
+ colors.clear
+ colors.add new Color(0.9, 0.6, 0.0)
+ colors.add new Color(0.6, 0.0, 0.9)
+ colors.add new Color(0.6, 0.5, 0.4)
+ colors.add new Color(1.0, 0.0, 0.0)
+ colors.add new Color(1.0, 1.0, 0.0)
+ colors.add new Color(1.0, 0.0, 1.0)
+ colors.add new Color(0.0, 1.0, 0.0)
+ colors.add new Color(0.0, 1.0, 1.0)
+ colors.add new Color(0.0, 0.0, 1.0)
+
+ drawing.load_all(self)
+ shapes.clear
+ shapes.add drawing.circle
+ shapes.add drawing.rect
+ shapes.add drawing.cross
+ shapes.add drawing.penta
+ shapes.add drawing.star
+ shapes.add drawing.triangle
+ shapes.add drawing.heart
+ shapes.add drawing.diamond
+ shapes.add drawing.moon
+ shapes.add drawing.spiral
+
+ number_images = new NumberImages(drawing.n)
+
+ sounds.clear
+ sounds.add new Sound("bing.wav")
+ sounds.add new Sound("boing.wav")
+ sounds.add new Sound("cymbal.wav")
+ sounds.add new Sound("dart.wav")
+ sounds.add new Sound("duh.wav")
+ sounds.add new Sound("grunt.wav")
+ sounds.add new Sound("honkhonk.wav")
+ sounds.add new Sound("line_end.wav")
+ sounds.add new Sound("squishy-hit.wav")
+ sounds.add new Sound("woodthunk.wav")
+ sounds.add new Sound("whip.wav")
+
+ snd_penalty = new Sound("penalty.wav")
+ snd_click = new Sound("click.wav")
+
+ # Force load the sounds. Required because bug #1728
+ for s in sounds do s.load
+ snd_penalty.load
+
+ is_menu = data_store["game"] != true
+ mode = data_int("mode") or else 0
+ current_level = data_int("level") or else 0
+
+ max_levels[0] = data_int("max_0") or else 0
+ max_levels[1] = data_int("max_1") or else 0
+ max_levels[2] = data_int("max_2") or else 0
+
+ print "max_levels: {max_levels}"
+
+ reload = new Button(-1, new Color(1.0,1.0,1.0), drawing.reload, snd_click)
+
+ if is_menu then
+ new_menu
+ else
+ new_game
+ end
+ end
+
+ # Get a positive numeric value from the store
+ fun data_int(name: String): nullable Int
+ do
+ var x = data_store[name]
+ if x isa Int then return x else return null
+ end
+
+ # # Level information
+
+ # Number of buttons for the next game
+ var size = 5
+
+ # Length of the memory sequence for the next game
+ var length = 5
+
+ # Do a hard deal?
+ var hard_deal = false
+
+ # No shuffle (0), easy shuffle (1), or hard shuffle (2)?
+ var shuffling = 0
+
+ # Is a new deal make on replay?
+ # If true, a new set of figures and a new sequence is produced
+ # If false, the same is reused.
+ var deal_on_replay = true
+
+ # Current buttons in the game
+ var buttons = new Array[Button]
+
+ # The sequence of the buttons to memorize
+ var level = new Array[Button]
+
+ # The number of errors (crosses) in the current level. (in [0..3])
+ var error = 0
+
+ # Is the player playing?
+ # If false it means that the game is showing the sequence to memorize
+ var player = false
+
+ # Next button on the level (to show or guess according to `player`)
+ var cpt = 0
+
+ # Time to live before the next event
+ var ttl = 0.0
+
+ # Are we in the menu?
+ var is_menu = true
+
+ # In the end of game, is this a win of a lose?
+ var is_win = false
+
+ # Reset everything and create a menu
+ fun new_menu
+ do
+ is_menu = true
+ size = 3
+ length = 0
+ shuffling = 0
+
+ data_store["game"] = false
+
+ colors.shuffle
+ shapes.shuffle
+ sounds.shuffle
+
+ buttons.clear
+ for i in [0..size[ do
+ var b = new Button(i, colors[i], shapes[i], sounds[i])
+ buttons.add b
+ b.text = drawing.hard[i]
+ b.text_color = colors[3+i]
+ b.text_max = max_levels[i]
+ end
+
+ # Start the scene
+ start_scene
+ end
+
+ # The current mode: easy (0), medium (1), hard (2)
+ var mode = 0
+
+ # The current level (from 0)
+ var current_level = 0
+
+ # Hight scores of each mode
+ var max_levels: Array[Int] = [0, 0, 0]
+
+ # Reset everything and create a new game using `mode` and `level`
+ fun new_game
+ do
+ print "Next game: mode={mode} level={current_level}"
+ data_store["game"] = true
+ data_store["mode"] = mode
+ data_store["level"] = current_level
+ if max_levels[mode] < current_level then
+ max_levels[mode] = current_level
+ data_store["max_{mode}"] = current_level
+ end
+
+ if mode == 0 then
+ hard_deal = false
+ shuffling = 0
+ deal_on_replay = false
+ size = 2
+ length = 1
+ else if mode == 1 then
+ hard_deal = false
+ shuffling = 1
+ deal_on_replay = true
+ size = 3
+ length = 3
+ else
+ hard_deal = true
+ shuffling = 2
+ deal_on_replay = true
+ size = 3
+ length = 3
+ end
+ for i in [0..current_level[ do
+ length += 1
+ if length > size + 2 then
+ size += 1
+ length -= 1
+ end
+ if size > 16 then size = 16
+ end
+
+ deal_game
+ end
+
+ # Reset the buttons and deal a new game using `size` and `length`
+ fun deal_game
+ do
+ is_menu = false
+
+ # Randomize the deal
+ colors.shuffle
+ shapes.shuffle
+ sounds.shuffle
+
+ # Setup the figure
+ buttons.clear
+ if not hard_deal then
+ # With the easy deal, each button is easily distinguishable
+ for i in [0..size[ do
+ var b = new Button(i, colors[i%colors.length], shapes[i%shapes.length], sounds[i%sounds.length])
+ buttons.add b
+ end
+ else
+ # With the hard deal, use overlapping combinations of colors and shapes
+ var sqrt = size.to_f.sqrt
+ var ncol = sqrt.floor.to_i
+ var nsha = sqrt.ceil.to_i
+ while ncol*nsha < size do ncol += 1
+
+ # Randomly swap the numbers of colors/shapes
+ if 2.rand == 0 then
+ var t = ncol
+ ncol = nsha
+ nsha = t
+ end
+
+ # Deal combinations (up to `size`)
+ for i in [0..ncol[ do
+ for j in [0..nsha[ do
+ if buttons.length >= size then break
+ var b = new Button(buttons.length, colors[i], shapes[j], sounds.rand)
+ buttons.add b
+ end
+ end
+
+ # A last shuffle to break the colors/shapes grid
+ buttons.shuffle
+ end
+
+ # Deal the level (i.e. sequence to memorize)
+ # To increase distribution, determinate a maximum number of repetition
+ # of a single button
+ var rep = (length.to_f / size.to_f).ceil.to_i
+ var pool = buttons * rep
+ pool.shuffle
+
+ level.clear
+ for i in [0..length[ do
+ level.add pool[i]
+ end
+
+ print "newgame size={size} length={length}"
+
+ # Start the scene
+ start_scene
+ end
+
+ # Cause a replay on the same level
+ # On easy mode, the same level is replayed exactly
+ # On other modes, a new deal is made
+ fun replay_game
+ do
+ if deal_on_replay then
+ deal_game
+ else
+ start_scene
+ end
+ end
+
+ # Reset the state of the scene and start with `fly_in`
+ fun start_scene
+ do
+ player = false
+ cpt = -1
+ path = null
+ error = 0
+
+ # Ask for a redraw
+ first_frame = true
+ end
+
+ # # Placement and moves
+
+ # Locations used to place buttons on the screen
+ private var locations: Array[Array[Float]] = [
+ [0.0, 1.0],
+ [0.0, 1.0, 0.5],
+ [0.0, 1.0, 0.0, 1.0],
+ [0.0, 1.0, 2.0, 0.5, 1.5],
+ [0.0, 1.0, 2.0, 0.0, 1.0, 2.0],
+ [0.5, 1.5, 0.0, 1.0, 2.0, 0.5, 1.5],
+ [0.0, 1.0, 2.0, 0.0, 2.0, 0.0, 1.0, 2.0],
+ [0.0, 1.0, 2.0, 0.0, 1.0, 2.0, 0.0, 1.0, 2.0],
+ [0.5, 1.5, 2.5, 0.0, 1.0, 2.0, 3.0, 0.5, 1.5, 2.5],
+ [0.0, 1.0, 2.0, 3.0, 0.0, 1.5, 3.0, 0.0, 1.0, 2.0, 3.0],
+ [0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 3.0],
+ [0.5, 1.5, 2.5, 0.0, 1.5, 3.0, 0.0, 1.0, 2.0, 3.0, 0.5, 1.5, 2.5],
+ [0.5, 1.5, 2.5, 0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 3.0, 0.5, 1.5, 2.5],
+ [0.5, 1.5, 2.5, 0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 3.0],
+ [0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 3.0]]
+
+
+ # The scale of the figures.
+ # According to the screen dimensions and the number of figures
+ var scale = 0.0
+
+ # The scale of the UI
+ # According to the screen dimensions
+ var ui_scale = 0.0
+
+ # Compute then location on the display for each button
+ #
+ # The method can be called when there is a change in the buttons (or the display).
+ fun locate(display: Display)
+ do
+ # The locations depend of the number of buttons (from 2 to 9)
+ var n = buttons.length
+ var locs = locations[n-2]
+ var columns = if n <= 4 then 2 else if n <= 9 then 3 else 4
+ var rows = if n <= 2 then 1 else if n <= 6 then 2 else if n <= 12 then 3 else 4
+
+ # Compute basic dimensions according to the screen
+ var slotw = display.width / columns
+ var sloth = display.height / rows
+ var subw = slotw - slotw/5
+ var subh = sloth - sloth/5
+
+ # Compute the figure scale
+ var img = drawing.circle
+ var xs = subw.to_f / img.width.to_f
+ var ys = subh.to_f / img.height.to_f
+ scale = xs.min(ys)
+
+ # Compute the UI scale
+ xs = display.width.to_f / img.width.to_f
+ ys = display.height.to_f / img.height.to_f
+ ui_scale = xs.min(ys) / 4.0
+
+ var last = -1.0
+ var row = 0.0
+ var cpt = 0
+ for b in buttons do
+ b.place = cpt
+ var col = locs[cpt]
+ if col <= last then
+ row += 1.0
+ end
+ last = col
+
+ b.x = (col + 0.5) * slotw.to_f
+ b.y = (row + 0.5) * sloth.to_f
+ img = b.shape
+ img.scale = scale
+ b.w = (img.width.to_f * scale)
+ b.h = (img.height.to_f * scale)
+
+ cpt += 1
+ end
+
+ left.x = -150.0 * scale
+ left.y = (display.height / 2).to_f
+ right.x = display.width.to_f + 150.0 * scale
+ right.y = left.y
+
+ # Other UI elements
+
+ if not is_menu then
+ var reload = self.reload
+ drawing.reload.scale = ui_scale
+ reload.x = display.width.to_f - (drawing.reload.width.to_f / 2.0 * 1.2 ) * ui_scale
+ reload.y = drawing.reload.height.to_f / 2.0 * 1.2 * ui_scale
+ reload.w = drawing.reload.width.to_f * ui_scale
+ reload.h = drawing.reload.height.to_f * ui_scale
+ end
+ end
+
+ # The origin point of the cursor on the left
+ var left = new Pos(0.0, 0.0)
+
+ # The destination point of the cursor on the right
+ var right = new Pos(0.0, 0.0)
+
+ # The current cursor position
+ var cursor = new Pos(0.0, 0.0)
+
+ # The current cursor path
+ var path: nullable BPath = null
+
+ # The reload button
+ var reload: Button is noautoinit
+
+ # Safe point for a cursor on the i-th button of the level
+ fun path_pos(i: Int): Pos
+ do
+ if i < 0 then return left
+ if i >= level.length then return right
+ return level[i].to_pos
+ end
+
+ # A random point outside of the screen
+ fun far_away(display: Display): Pos
+ do
+ var a = (2.0*pi).rand
+ var w = display.width.to_f / 2.0
+ var h = display.height.to_f / 2.0
+ var x = w + a.cos * w * 1.8
+ var y = h + a.sin * h * 1.8
+ return new Pos(x, y)
+ end
+
+ # Create a BPath between two point with some nice handle values
+ fun new_path(from, to: Pos, ttl: Float): BPath
+ do
+ var a = atan2(to.y-from.y, to.x-from.x)
+ a += pi * (2.0.rand - 1.0)
+ var radius = 300.0 * scale
+ var fh = new Pos(from.x + a.cos*radius, from.y + a.sin*radius)
+ #var th = new Pos(to.x - a.cos*radius, to.y - a.sin*radius)
+ var path = new BPath(from, fh, to, to, ttl)
+ return path
+ end
+
+ # Initial placement of buttons
+ fun fly_in(display: Display)
+ do
+ for b in buttons do
+ var from = far_away(display)
+ var to = b.to_pos
+ var path = new_path(from, to, 5.0)
+ b.path = path
+ b.ttl = 5.0
+ end
+ ttl = 6.0
+ end
+
+ # Final leaving of buttons
+ fun fly_out(display: Display)
+ do
+ for b in buttons do
+ var from = b.to_pos
+ var to = far_away(display)
+ b.x = to.x
+ b.y = to.y
+ var path = new_path(from, to, 5.0)
+ b.path = path
+ b.ttl = 5.0
+ b.hard = false
+ end
+ ttl = 6.0
+ end
+
+ # Randomly permute the content of `buttons` such that no element appears in its original position.
+ fun derangement
+ do
+ # The simplest algorithm is to shuffle until no buttons is at the same place
+ # This is also quite efficient and converges extremely quickly
+ var redo = true
+ while redo do
+ redo = false
+ buttons.shuffle
+ for i in [0..size[ do
+ if i == buttons[i].place then
+ redo = true
+ break
+ end
+ end
+ end
+ end
+
+ # Shuffling the place of each button on the screen
+ fun shuffle(display: Display)
+ do
+ for b in buttons do
+ b.from = b.to_pos
+ end
+
+ derangement
+
+ locate(display)
+ for b in buttons do
+ var from = b.from
+ var to = b.to_pos
+ #print "shuffle move {b.place}: {from} -> {to}"
+ b.path = new_path(from, to, 5.0)
+ b.ttl = 5.0
+ end
+ ttl = 5.0
+ end
+
+ # Shuffle the place of each button in a hard way
+ fun hard_shuffle(display: Display)
+ do
+ for b in buttons do
+ b.from = b.to_pos
+ b.hard = true
+ end
+
+ derangement
+
+ locate(display)
+ for b in buttons do
+ var from = b.from
+ var to = b.to_pos
+ var midx = display.width.to_f / 2.0
+ var midy = display.height.to_f / 2.0
+ var mid = new Pos(midx, midy)
+ #print "shuffle move {b.place}: {from} -> {to}"
+ b.path = new_path(from, mid, 5.0)
+ b.path2 = new_path(mid, to, 5.0)
+ b.ttl = 5.0
+ end
+ ttl = 5.0
+ end
+
+ # Setup the next cursor path
+ fun setpath
+ do
+ if is_menu then return
+ var from = path_pos(cpt-1)
+ var to = path_pos(cpt)
+ #print "cursor {cpt-1}->{cpt}: {from} -> {to}"
+ path = new_path(from, to, 4.0)
+ cursor.x = from.x
+ cursor.y = from.y
+ ttl = 5.0
+ end
+
+ # Main loop, drawing and inputs
+
+ # Flag used to ask for a (re-)computation of the display layout
+ private var first_frame = true
+
+ redef fun frame_core(display)
+ do
+ if first_frame then
+ locate(display)
+ if cpt == -1 then
+ fly_in(display)
+ end
+ first_frame = false
+ end
+
+ # Clear the screen
+ display.clear(1.0, 1.0, 1.0)
+
+ # Manage events
+ # This is a crappy ad hoc organic implementation
+ if not player then
+ ttl -= 0.1
+ if path != null then path.update(cursor, ttl)
+ if ttl <= 0.0 then
+ ttl = 0.0
+ if is_menu then
+ # Menu animation is over
+ player = true
+ else if cpt < 0 then
+ # Level place animation is over
+ cpt += 1
+ setpath
+ else if cpt < level.length then
+ # The cursor is playing
+ var b = level[cpt]
+ b.ttl = 1.0
+ b.sound.play
+ cpt += 1
+ setpath
+ else if cpt == level.length then
+ # The cursor is out, run the shuffle
+ path = null
+ if shuffling == 1 then
+ shuffle(display)
+ else if shuffling > 1 then
+ hard_shuffle(display)
+ end
+ cpt += 1
+ else
+ # The shuffling is over, start playing
+ player = true
+ cpt = 0
+ end
+ end
+ else if ttl > 0.0 then
+ ttl -= 0.1
+ if ttl <= 0.0 then
+ ttl = 0.0
+ if cpt == level.length then
+ fly_out(display)
+ cpt += 1
+ else
+ if is_menu then
+ new_game
+ else if is_win then
+ current_level += 1
+ new_game
+ else
+ replay_game
+ end
+ end
+ end
+ end
+
+ # Display each button
+ for b in buttons do
+ b.blit_on(display)
+ end
+
+ # Display the cursor
+ if path != null then
+ drawing.cursor.scale = scale
+ display.blit(drawing.cursor, cursor.x, cursor.y)
+ end
+
+ if not is_menu then
+ blit_number(current_level, ui_scale, 10.0 * scale, 10.0 * scale)
+ reload.blit_on(display)
+ end
+ end
+
+ # Blit a number somewhere
+ fun blit_number(number: Int, scale: Float, x, y: Float)
+ do
+ for img in number_images.imgs do img.scale = scale
+ display.blit_number(number_images, number, x.to_i, y.to_i)
+ end
+
+ # Images with the numbers
+ private var number_images: NumberImages is noautoinit
+
+ # A player click on a button
+ fun action(b: Button)
+ do
+ if is_menu then
+ b.sound.play
+ mode = b.place
+ current_level = 0
+ ttl = 0.1
+ cpt = level.length
+ is_win = true
+ return
+ end
+ if cpt >= level.length then return
+ if b == level[cpt] then
+ b.sound.play
+ b.ttl = 1.0
+
+ cpt += 1
+ if cpt >= level.length then
+ is_win = true
+ print "Won!"
+ ttl = 2.0
+ end
+ else
+ error += 1
+ print "Err {error}"
+ b.error = true
+ b.ttl = 3.0
+ snd_penalty.play
+ if error > 2 then
+ is_win = false
+ print "Lose!"
+ for b2 in buttons do
+ b2.error = true
+ b2.ttl = 3.0
+ end
+ ttl = 3.0
+ cpt = level.length
+ end
+ end
+ end
+
+ redef fun input(ie)
+ do
+ # Quit?
+ if ie isa QuitEvent then
+ quit = true
+ return true
+ end
+
+ # On click (or tap)
+ if ie isa PointerEvent and ie.depressed then
+ if player then
+ for b in buttons do
+ if b.has(ie.x, ie.y) then
+ action(b)
+ return true
+ end
+ end
+ end
+
+ if not is_menu then
+ if reload.has(ie.x, ie.y) then
+ reload.sound.play
+ reload.ttl = 1.0
+ replay_game
+ return true
+ end
+ end
+ end
+
+ # Special commands
+ if ie isa KeyEvent and ie.is_down then
+ var c = ie.name
+
+ if c == "4" or c == "escape" then
+ # 4 is *back* on android
+ if is_menu then
+ # quit = true # broken
+ new_menu
+ else
+ new_menu
+ end
+ return true
+ end
+
+ if is_menu then
+ return false
+ end
+
+ if c == "[+]" or c == "=" then
+ # [+] is keypad `+`
+ size += 1
+ deal_game
+ return true
+ else if c == "[-]" or c == "-" then
+ size -= 1
+ deal_game
+ return true
+ else if c == "[*]" or c == "]" then
+ length += 1
+ deal_game
+ return true
+ else if c == "[/]" or c == "[" then
+ length -= 1
+ deal_game
+ return true
+ else if c == "space" or c == "82" then
+ # 82 is *menu* on android
+ reload.sound.play
+ reload.ttl = 1.0
+ replay_game
+ return true
+ end
+
+ print "got keydown: `{c}`"
+ end
+
+ return false
+ end
+end
[package]
name=mnit_test
-tags=
+tags=testing
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
license=Apache-2.0
[upstream]
else
add("\tredef fun trans(char) do\n")
- add("\t\tvar c = char.ascii\n")
+ add("\t\tvar c = char.code_point\n")
var haslast = false
var last = -1
for sym, next in trans do
if f <= 32 then
res = "#{f}"
else
- res = f.ascii.to_s
+ res = f.code_point.to_s
end
var l = last
if f == l then return res
res += " .. "
if l == null then return res
if l <= 32 or l >= 127 then return res + "#{l}"
- return res + l.ascii.to_s
+ return res + l.code_point.to_s
end
end
if text != null then
var nfa = new Automaton.epsilon
for c in text.chars do
- nfa.concat(new Automaton.atom(c.ascii))
+ nfa.concat(new Automaton.atom(c.code_point))
end
return nfa
end
do
var a = new Automaton.epsilon
for c in self.value.chars do
- var b = new Automaton.atom(c.ascii)
+ var b = new Automaton.atom(c.code_point)
a.concat(b)
end
return a
end
redef class Nch_dec
- redef fun value: String do return text.substring_from(1).to_i.ascii.to_s
+ redef fun value: String do return text.substring_from(1).to_i.code_point.to_s
redef fun make_rfa: Automaton
do
- var a = new Automaton.atom(self.value.chars.first.ascii)
+ var a = new Automaton.atom(self.value.chars.first.code_point)
return a
end
end
redef class Nch_hex
- redef fun value: String do return text.substring_from(2).to_hex.ascii.to_s
+ redef fun value: String do return text.substring_from(2).to_hex.code_point.to_s
redef fun make_rfa: Automaton
do
- var a = new Automaton.atom(self.value.chars.first.ascii)
+ var a = new Automaton.atom(self.value.chars.first.code_point)
return a
end
end
exit(1)
abort
end
- var a = new Automaton.cla(c1.chars.first.ascii, c2.chars.first.ascii)
+ var a = new Automaton.cla(c1.chars.first.code_point, c2.chars.first.code_point)
return a
end
end
# * `"0;32"` for green
fun colored_line(color: String): String
do
- var esc = 27.ascii
+ var esc = 27.code_point
var def = "{esc}[0m"
var col = "{esc}[{color}m"
end
redef class ACharValue
- redef fun to_i do return n_char.content.first.ascii
+ redef fun to_i do return n_char.content.first.code_point
end
redef class AStringValue
# legal but no not recommended
- redef fun to_i do return n_string.content.first.ascii
+ redef fun to_i do return n_string.content.first.code_point
end
redef class AHexValue
if sp >= string_len then
dfa_state = -1
else
- var c = string[sp].ascii
+ var c = string[sp].code_point
if c >= 255 then c = 255
sp += 1
[package]
name=draw_operation
-tags=
+tags=example
maintainer=Alexis Laferrière <alexis.laf@xymus.net>
license=Apache-2.0
[upstream]
continue
end
- out.add(((c.ascii + key[j].ascii - 2 * 'A'.ascii) % 26 + 'A'.ascii).ascii)
+ out.add(((c.ascii + key[j].ascii - 2u8 * 'A'.ascii) % 26u8 + 'A'.ascii).ascii)
j = (j + 1) % key.length
end
continue
end
- out.add(((c.ascii - key[j].ascii + 26) % 26 + 'A'.ascii).ascii)
+ out.add(((c.ascii - key[j].ascii + 26u8) % 26u8 + 'A'.ascii).ascii)
j = (j + 1) % key.length
end
# assert "string".encode_base64 == "c3RyaW5n"
private fun encode_base64(length: Int, padding: nullable Byte): Bytes do
var base64_bytes = once base64_chars
- if padding == null then padding = '='.ascii.to_b
+ if padding == null then padding = '='.ascii
var steps = length / 3
var bytes_in_last_step = length % 3
var result_length = steps * 4
#
# REQUIRE: `length % 4 == 0`
private fun decode_base64(length: Int, padding: nullable Byte): Bytes do
- if padding == null then padding = '='.ascii.to_b
+ if padding == null then padding = '='.ascii
var inv = once inverted_base64_chars
if length == 0 then return new Bytes.empty
assert length % 4 == 0 else print "base64::decode_base64 only supports strings of length multiple of 4"
#write(true, "C0".to_hex)
# instead we use the following which may not be portable
- for s in [count..40[ do write(false, ' '.ascii)
+ for s in [count..40[ do write(false, ' '.code_point)
count = 0
else
- write(false, c.ascii)
+ write(false, c.code_point)
count += 1
end
end
# Compared to `write_string`, this method supports null bytes in `text`.
fun write_block(text: Text)
do
- write_int64 text.length
+ write_int64 text.bytelen
write text
end
do
var length = read_int64
if length == 0 then return ""
- return read(length)
+ return read_bytes(length).to_s
end
# Read a floating point on 32 bits and return it as a `Float`
# The serialized data format uses a dictionary structure similar to BSON:
#
# ~~~raw
-# object = 0x01 # null
-# | 0x02 id attributes # New object
-# | 0x03 id # Ref to object
-# | 0x04 int64 # Int
-# | 0x05 int8 # Bool (int8 != 0)
-# | 0x06 int8 # Char
-# | 0x07 double(64 bits) # Float
-# | 0x08 block # String
-# | 0x09 block # NativeString
-# | 0x0A flat_array; # Array[nullable Object]
+# object = 0x01 # null
+# | 0x02 id attributes # New object
+# | 0x03 id # Ref to object
+# | 0x04 int64 # Int
+# | 0x05 int8 # Bool (int8 != 0)
+# | 0x06 utf8 byte sequence # Char
+# | 0x07 double(64 bits) # Float
+# | 0x08 block # String
+# | 0x09 block # NativeString
+# | 0x0A flat_array; # Array[nullable Object]
#
# block = int64 int8*;
# cstring = int8* 0x00;
# Tree of attributes, deserialized but not yet claimed
private var unclaimed_attributes = new UnrolledList[HashMap[String, nullable Object]]
+ # Buffer for one char
+ private var char_buf: NativeString is lazy do return new NativeString(4)
+
# Read and deserialize the next attribute name and value
#
# A `peeked_char` can suffix the next attribute name.
if kind == kind_bool then return stream.read_bool
if kind == kind_float then return stream.read_double
if kind == kind_char then
+ var bf = char_buf
var b = stream.read_byte
- if b == null then return 0
- return b.to_i.ascii
+ if b == null then return '�'
+ var ln = b.u8len
+ bf[0] = b
+ for i in [1 .. ln[ do
+ b = stream.read_byte
+ if b == null then return '�'
+ bf[i] = b
+ end
+ return bf.to_s_with_length(ln)[0]
end
if kind == kind_string then return stream.read_block
if kind == kind_native_string then return stream.read_block.to_cstring
redef fun serialize_to_binary(v)
do
v.stream.write_byte kind_char
- # Fix when UTF-8
- v.stream.write_byte self.ascii.to_b
+ for i in bytes do v.stream.write_byte i
end
end
var fw = new FileWriter.open(path)
# Write bitmap header
for x in [0..self.bitmap_header.length[ do
- fw.write(self.bitmap_header[x].ascii.to_s)
+ fw.write(self.bitmap_header[x].code_point.to_s)
end
# Write dib header
for x in [0..self.dib_header.length[ do
- fw.write(self.dib_header[x].ascii.to_s)
+ fw.write(self.dib_header[x].code_point.to_s)
end
# Write color table (if any)
# Write data (no padding for now)
var red = pixel >> 16
var green = (pixel & 0x00FF00) >> 8
var blue = pixel & 0x000000FF
- fw.write(red.ascii.to_s)
- fw.write(green.ascii.to_s)
- fw.write(blue.ascii.to_s)
+ fw.write(red.code_point.to_s)
+ fw.write(green.code_point.to_s)
+ fw.write(blue.code_point.to_s)
end
end
fw.close
redef fun substrings do return new LeafSubstrings(self)
- redef fun [](i) do return buf[i].to_i.ascii
+ redef fun [](i) do return buf[i].to_i.code_point
init do
bns = buf.ns
# A ANSI/VT100 escape sequence.
abstract class TermEscape
# The US-ASCII ESC character.
- protected fun esc: Char do return 27.ascii
+ protected fun esc: Char do return 27.code_point
# The Control Sequence Introducer (CSI).
protected fun csi: String do return "{esc}["
#
# ~~~nit
# intrude import core::bytes
- # assert not '/'.ascii.to_b.is_valid_hexdigit
- # assert '0'.ascii.to_b.is_valid_hexdigit
- # assert '9'.ascii.to_b.is_valid_hexdigit
- # assert not ':'.ascii.to_b.is_valid_hexdigit
- # assert not '@'.ascii.to_b.is_valid_hexdigit
- # assert 'A'.ascii.to_b.is_valid_hexdigit
- # assert 'F'.ascii.to_b.is_valid_hexdigit
- # assert not 'G'.ascii.to_b.is_valid_hexdigit
- # assert not '`'.ascii.to_b.is_valid_hexdigit
- # assert 'a'.ascii.to_b.is_valid_hexdigit
- # assert 'f'.ascii.to_b.is_valid_hexdigit
- # assert not 'g'.ascii.to_b.is_valid_hexdigit
+ # assert not '/'.ascii.is_valid_hexdigit
+ # assert '0'.ascii.is_valid_hexdigit
+ # assert '9'.ascii.is_valid_hexdigit
+ # assert not ':'.ascii.is_valid_hexdigit
+ # assert not '@'.ascii.is_valid_hexdigit
+ # assert 'A'.ascii.is_valid_hexdigit
+ # assert 'F'.ascii.is_valid_hexdigit
+ # assert not 'G'.ascii.is_valid_hexdigit
+ # assert not '`'.ascii.is_valid_hexdigit
+ # assert 'a'.ascii.is_valid_hexdigit
+ # assert 'f'.ascii.is_valid_hexdigit
+ # assert not 'g'.ascii.is_valid_hexdigit
# ~~~
private fun is_valid_hexdigit: Bool do
return (self >= 0x30u8 and self <= 0x39u8) or
# Iterate over `self`
fun iterator: Iterator[E] do return self
+ # Pre-iteration hook.
+ #
+ # Used to inform `self` that the iteration is starting.
+ # Specific iterators can use this to prepare some resources.
+ #
+ # Is automatically invoked at the beginning of `for` structures.
+ #
+ # Do nothing by default.
+ fun start do end
+
# Post-iteration hook.
#
# Used to inform `self` that the iteration is over.
# Set a new `item` at `key`.
#fun item=(item: E) is abstract
+ # Pre-iteration hook.
+ #
+ # Used to inform `self` that the iteration is starting.
+ # Specific iterators can use this to prepare some resources.
+ #
+ # Is automatically invoked at the beginning of `for` structures.
+ #
+ # Do nothing by default.
+ fun start do end
+
# Post-iteration hook.
#
# Used to inform `self` that the iteration is over.
redef fun to_i32 is intern
redef fun to_u32 is intern
+ # Returns `self` as a Char according to its ASCII value.
+ fun ascii: Char `{ return (uint32_t)self; `}
+
redef fun distance(i) do return (self - i).to_i
redef fun <=>(other)
redef fun *(i) is intern
redef fun /(i) is intern
+ # Returns `self` as a Char according to its ASCII value.
+ fun ascii: Char `{ return (uint32_t)self; `}
+
# Modulo of `self` with `i`.
#
# Returns the remainder of division of `self` by `i`.
redef fun zero do return 0.to_u16
redef fun value_of(val) do return val.to_u16
+ # Returns `self` as a Char according to its ASCII value.
+ fun ascii: Char `{ return (uint32_t)self; `}
+
# `i` bits shift to the left
#
# assert 5u16 << 1 == 10u16
redef fun *(i) is intern
redef fun /(i) is intern
+ # Returns `self` as a Char according to its ASCII value.
+ fun ascii: Char `{ return (uint32_t)self; `}
+
# Modulo of `self` with `i`.
#
# Returns the remainder of division of `self` by `i`.
redef fun *(i) is intern
redef fun /(i) is intern
+ # Returns `self` as a Char according to its ASCII value.
+ fun ascii: Char `{ return (uint32_t)self; `}
+
# Modulo of `self` with `i`.
#
# Returns the remainder of division of `self` by `i`.
# assert 5u8 >> 1 == 2u8
fun >>(i: Int): Byte `{ return self >> i; `}
+ # Returns the character equivalent of `self`
+ #
+ # REQUIRE: `self <= 127u8`
+ fun ascii: Char `{ return (uint32_t)self; `}
+
redef fun to_i is intern
redef fun to_f is intern
redef fun to_b do return self
end
end
- # The character whose ASCII value is `self`.
+ # The character which code point (unicode-wise) is `self`
#
- # assert 65.ascii == 'A'
- # assert 10.ascii == '\n'
- fun ascii: Char is intern
+ # assert 65.code_point == 'A'
+ # assert 10.code_point == '\n'
+ # assert 0x220B.code_point == '∋'
+ fun code_point: Char `{ return (uint32_t)self; `}
# Number of digits of an integer in base `b` (plus one if negative)
#
do
assert self >= 0 and self <= 36 # TODO plan for this
if self < 10 then
- return (self + '0'.ascii).ascii
+ return (self + '0'.code_point).code_point
else
- return (self + ('a'.ascii - 10)).ascii
+ return (self - 10 + 'a'.code_point).code_point
end
end
printf("%c", self);
}
`}
- redef fun hash do return ascii
+ redef fun hash do return code_point
redef fun ==(o) is intern
redef fun !=(o) is intern
redef fun distance(c)
do
- var d = self.ascii - c.ascii
+ var d = self.code_point - c.code_point
if d >= 0 then
return d
else
if self == '-' then
return -1
else if is_digit then
- return self.ascii - '0'.ascii
+ return self.code_point - '0'.code_point
else
- return self.to_lower.ascii - 'a'.ascii + 10
+ return self.to_lower.code_point - 'a'.code_point + 10
end
end
- # the ascii value of self
+ # The ascii value of `self`
+ #
+ # assert 'a'.ascii == 97u8
+ # assert '\n'.ascii == 10u8
+ #
+ # REQUIRE: `is_ascii`
+ fun ascii: Byte do return code_point.to_b
+
+ # The unicode code point value of `self`
+ #
+ # assert 'A'.code_point == 65
+ # assert '\n'.code_point == 10
+ # assert '∋'.code_point == 0x220B
+ fun code_point: Int `{ return (long)self; `}
+
+ # Is `self` an ASCII character ?
#
- # assert 'a'.ascii == 97
- # assert '\n'.ascii == 10
- fun ascii: Int is intern
+ # assert 'x'.is_ascii
+ # assert not 'ま'.is_ascii
+ fun is_ascii: Bool do return code_point <= 127
# Return the lower case version of self.
# If self is not a letter, then return self
fun to_lower: Char
do
if is_upper then
- return (ascii + ('a'.distance('A'))).ascii
+ return (code_point + ('a'.distance('A'))).code_point
else
return self
end
fun to_upper: Char
do
if is_lower then
- return (ascii - ('a'.distance('A'))).ascii
+ return (code_point - ('a'.distance('A'))).code_point
else
return self
end
# assert '\t'.is_whitespace == true
fun is_whitespace: Bool
do
- var i = ascii
+ var i = code_point
return i <= 0x20 or i == 0x7F
end
end
# assert -0.5.lerp(0.0, 128.0) == -64.0
# ~~~
fun lerp(a, b: Float): Float do return (1.0 - self) * a + self * b
+
+ # Quadratic Bézier interpolation between `a` and `b` with an `handle` using `self` as weight
+ #
+ # ~~~
+ # assert 0.00.qerp(0.0, 32.0, 128.0) == 0.0
+ # assert 0.25.qerp(0.0, 32.0, 128.0) == 20.0
+ # assert 0.50.qerp(0.0, 32.0, 128.0) == 48.0
+ # assert 0.75.qerp(0.0, 32.0, 128.0) == 84.0
+ # assert 1.00.qerp(0.0, 32.0, 128.0) == 128.0
+ # ~~~
+ fun qerp(a, handle, b: Float): Float do
+ var p = self
+ var i = 1.0 - p
+ var r = i*i * a +
+ 2.0*i*p * handle +
+ p*p * b
+ return r
+ end
+
+ # Cubic Bézier interpolation between `a` and `b` with two handles using `self` as weight
+ #
+ # The Cubic Bézier interpolation is the most common one and use two control points.
+ #
+ # ~~~
+ # assert 0.00.cerp(0.0, 32.0, 128.0, 64.0) == 0.0
+ # assert 0.25.cerp(0.0, 32.0, 128.0, 64.0) == 32.5
+ # assert 0.50.cerp(0.0, 32.0, 128.0, 64.0) == 68.0
+ # assert 0.75.cerp(0.0, 32.0, 128.0, 64.0) == 85.5
+ # assert 1.00.cerp(0.0, 32.0, 128.0, 64.0) == 64.0
+ # ~~~
+ fun cerp(a, a_handle, b_handle, b: Float): Float do
+ var p = self
+ var i = 1.0 - p
+ var r = i*i*i * a +
+ 3.0*i*i*p * a_handle +
+ 3.0*i*p*p * b_handle +
+ p*p*p * b
+ return r
+ end
end
# Positive float infinite (IEEE 754)
# close the stream
fun close is abstract
+
+ # Pre-work hook.
+ #
+ # Used to inform `self` that operations will start.
+ # Specific streams can use this to prepare some resources.
+ #
+ # Is automatically invoked at the beginning of `with` structures.
+ #
+ # Do nothing by default.
+ fun start do end
+
+ # Post-work hook.
+ #
+ # Used to inform `self` that the operations are over.
+ # Specific streams can use this to free some resources.
+ #
+ # Is automatically invoked at the end of `woth` structures.
+ #
+ # call `close` by default.
+ fun finish do close
end
# A `Stream` that can be read from
# ~~~
# var w = new StringReader(" Hello, \n\t World!")
# assert w.read_word == "Hello,"
- # assert w.read_char == '\n'.ascii
+ # assert w.read_char == '\n'
# assert w.read_word == "World!"
# assert w.read_word == ""
# ~~~
end
end
+redef class Bytes
+ super Writable
+ redef fun write_to(s) do s.write_bytes(self)
+
+ redef fun write_to_string do return to_s
+end
+
redef class Text
super Writable
redef fun write_to(stream) do stream.write(self)
return null
end
# TODO: Fix when supporting UTF-8
- var c = _buffer[_buffer_pos].to_i.ascii
+ var c = _buffer[_buffer_pos].to_i.code_point
_buffer_pos += 1
return c
end
if c >= '0' and c <= '9' then
res.add('_')
- res.append(c.ascii.to_s)
+ res.append(c.code_point.to_s)
res.add('d')
start = 1
end
continue
end
if underscore then
- res.append('_'.ascii.to_s)
+ res.append('_'.code_point.to_s)
res.add('d')
end
if c >= '0' and c <= '9' then
underscore = true
else
res.add('_')
- res.append(c.ascii.to_s)
+ res.append(c.code_point.to_s)
res.add('d')
underscore = false
end
end
if underscore then
- res.append('_'.ascii.to_s)
+ res.append('_'.code_point.to_s)
res.add('d')
end
return res.to_s
# Three digits are always used to avoid following digits to be interpreted as an element
# of the octal sequence.
#
- # assert "{0.ascii}{1.ascii}{8.ascii}{31.ascii}{32.ascii}".escape_to_c == "\\000\\001\\010\\037 "
+ # assert "{0.code_point}{1.code_point}{8.code_point}{31.code_point}{32.code_point}".escape_to_c == "\\000\\001\\010\\037 "
#
# The exceptions are the common `\t` and `\n`.
fun escape_to_c: String
b.append("\\\'")
else if c == '\\' then
b.append("\\\\")
- else if c.ascii < 32 then
+ else if c.code_point < 32 then
b.add('\\')
- var oct = c.ascii.to_base(8, false)
+ var oct = c.code_point.to_base(8, false)
# Force 3 octal digits since it is the
# maximum allowed in the C specification
if oct.length == 1 then
else if c == ':' or c == ' ' or c == '#' then
b.add('\\')
b.add(c)
- else if c.ascii < 32 or c == ';' or c == '|' or c == '\\' or c == '=' then
- b.append("?{c.ascii.to_base(16, false)}")
+ else if c.code_point < 32 or c == ';' or c == '|' or c == '\\' or c == '=' then
+ b.append("?{c.code_point.to_base(16, false)}")
else
b.add(c)
end
# assert s.length == 2
# var u = s.unescape_nit
# assert u.length == 1
- # assert u.chars[0].ascii == 10 # (the ASCII value of the "new line" character)
+ # assert u.chars[0].code_point == 10 # (the ASCII value of the "new line" character)
fun unescape_nit: String
do
var res = new Buffer.with_cap(self.length)
if c == '%' then
if i + 2 >= length then
# What follows % has been cut off
- buf[l] = '?'.ascii.to_b
+ buf[l] = '?'.ascii
else
i += 1
var hex_s = substring(i, 2)
i += 1
else
# What follows a % is not Hex
- buf[l] = '?'.ascii.to_b
+ buf[l] = '?'.ascii
i -= 1
end
end
- else buf[l] = c.ascii.to_b
+ else buf[l] = c.ascii
i += 1
l += 1
for i in [0..length[ do
var char = chars[i]
- h = (h << 5) + h + char.ascii
+ h = (h << 5) + h + char.code_point
end
hash_cache = h
redef fun is_empty do return target.is_empty
- redef fun length do return target.length
+ redef fun length do return target.bytelen
redef fun iterator do return self.iterator_from(0)
redef class Char
+ # Returns a sequence with the UTF-8 bytes of `self`
+ #
+ # assert 'a'.bytes == [0x61u8]
+ # assert 'ま'.bytes == [0xE3u8, 0x81u8, 0xBEu8]
+ fun bytes: SequenceRead[Byte] do return to_s.bytes
+
# Length of `self` in a UTF-8 String
private fun u8char_len: Int do
- var c = self.ascii
+ var c = self.code_point
if c < 0x80 then return 1
if c <= 0x7FF then return 2
if c <= 0xFFFF then return 3
end
var ok_c: Bool
var c = char_at(pos)
- var cp = c.ascii
+ var cp = c.code_point
if nxst == 1 then
ok_c = cp >= 0 and cp <= 0x7F
else if nxst == 2 then
redef class Byte
# Gives the length of the UTF-8 char starting with `self`
- private fun u8len: Int do
+ fun u8len: Int do
if self & 0b1000_0000u8 == 0u8 then
return 1
else if self & 0b1110_0000u8 == 0b1100_0000u8 then
rp = 0
end
# TODO: Fix when supporting UTF-8
- ns[rp] = c.ascii.to_b
+ ns[rp] = c.ascii
rp += 1
_bytelen += 1
rpos = rp
x = x % 26
if x < 0 then x += 26
var up = false
- var val = ascii
+ var val = code_point
if is_upper then
up = true
val += 32
val += x
if val > 122 then val -= 26
if up then val -= 32
- return val.ascii
+ return val.code_point
end
end
--- /dev/null
+[package]
+name=gen_nit
+tags=devel
+maintainer=Alexis Laferrière <alexis.laf@xymus.net>
+license=Apache-2.0
+[upstream]
+browse=https://github.com/nitlang/nit/tree/master/lib/gen_nit.nit
+git=https://github.com/nitlang/nit.git
+git.directory=lib/gen_nit.nit
+homepage=http://nitlanguage.org
+issues=https://github.com/nitlang/nit/issues
--- /dev/null
+Basic geometry data structures and services.
+
+# Points and Lines
+
+The very basics of geometry needs, for two and three-dimensional space.
+
+# Boxes and detection collision
+
+Boxes module introduces Bounding boxes for Points and Lines and services to detect collision or inclusion between boxes.
+It means a simple and fast way to test collision but not really accurate since it uses bounding boxes.
+
+# Quadtrees
+
+A QuadTree is a tree data structure in which each internal node has exactly four children
+They're most often used to partition two-dimensional space by recursively subdividing
+it into four quadrants or regions.
+
+* They decompose space into adaptable cells
+* Each cell has a maximum capacity. When maximum is reached, the cell splits.
+
+Quadtrees are using Boxed objects to determine their distribution in the 2D space.
+
+This API provides two different types of Quadtree : Static and Dynamic (respectively `SQuadTree` and `DQuadTree`).
+
+* Static: When you create the QuadTree, you need to specify the region that it will cover
+
+* Dynamic: You just need to fill the quadtree with objects, and when the threshold is reached,
+it will automatically divide the current region, depending on the distribution of objects already in the region.
+
+# Polygons
+
+Some basic polygon services.
+
+This module contains interesting algorithms for `ConvexPolygon`only at the moment. A Convex polygon can be defined as follow :
+
+* All its interior angles are less than 180°. this means that all the vertices of the polygon
+will point outwards, away from the interior of the shape.
+
+* Every point on every line segment between two points inside or on the boundary of the polygon
+remains inside or on the boundary.
+
+* The polygon is entirely contained in a closed half-plane defined by each of its edges.
+
+* For each edge, the interior points are all on the same side of the line that the edge defines.
+
+* The angle at each vertex contains all other vertices in its edges and interior.
+
+A polygon which is not convex is called concave. Convex polygon are used because most
+geometric problems are simpler and faster on convex objects than on non-convex ones.
+
+Services provided :
+
+* Point in convex polygon
+* Intersection of convex polygon
+* Convex hull of a set of points
+* Triangulation of polygon
import points_and_lines
-# Convex Polygon class
-class ConvexPolygon
-
+# Abstraction of a Polygon
+abstract class APolygon
# Vertices of this polygon
- var points = new Array[Point[Float]]
+ var points: Array[Point[Float]]
- # Init this polygon with a list of `points`
- # REQUIRE `pts.length == 3`
- init with_vertices(pts: Array[Point[Float]]) do
- assert pts.length >= 3
- points.add_all(pts)
- end
+ init do assert points.length >= 3
# Get an array of the x coordinates of the vertices
private fun x_coordinates: Array[Float] do
# var p3 = new Point[Float](0.0, 5.0)
# var p4 = new Point[Float](5.0, 5.0)
# var arr = new Array[Point[Float]].with_items(p1, p2, p3, p4)
- # var poly = new ConvexPolygon.with_vertices(arr)
+ # var poly = new ConvexPolygon(arr)
# poly.sort_ccw
# assert poly.points == [p4, p2, p1, p3]
# ~~~
# var p3 = new Point[Float](0.0, 5.0)
# var p4 = new Point[Float](5.0, 5.0)
# var arr = new Array[Point[Float]].with_items(p1, p2, p3, p4)
- # var poly = new ConvexPolygon.with_vertices(arr)
+ # var poly = new ConvexPolygon(arr)
# poly.sort_cw
# assert poly.points == [p3, p1, p2, p4]
# ~~~
sorter.sort(points)
end
- # Does this polygon intersects `other` ?
+ # Is `self` convex ?
#
# ~~~
# var p1 = new Point[Float](0.0, 0.0)
# var p3 = new Point[Float](0.0, 5.0)
# var p4 = new Point[Float](5.0, 5.0)
# var arr = new Array[Point[Float]].with_items(p1, p2, p3, p4)
- # var poly = new ConvexPolygon.with_vertices(arr)
+ # var poly = new ConvexPolygon(arr)
# poly.sort_ccw
- # p1 = new Point[Float](2.5, 2.5)
- # p2 = new Point[Float](7.5, 2.5)
- # p3 = new Point[Float](2.5, 7.5)
- # p4 = new Point[Float](7.5, 7.5)
- # arr = new Array[Point[Float]].with_items(p1, p2, p3, p4)
- # var poly2 = new ConvexPolygon.with_vertices(arr)
- # poly2.sort_ccw
- # assert poly.intersects(poly2)
+ # assert poly.is_convex
# ~~~
- fun intersects(other: ConvexPolygon): Bool do
- assert is_convex
-
- var axes1 = axes
- var axes2 = other.axes
- for axis in axes1 do
- var project1 = project(axis)
- var project2 = other.project(axis)
- if not project1.overlap(project2) then return false
- end
- for axis in axes2 do
- var project1 = project(axis)
- var project2 = other.project(axis)
- if not project1.overlap(project2) then return false
+ fun is_convex: Bool do
+ var prev = points[points.length - 2]
+ var curr = points[points.length - 1]
+ var next = points[0]
+ var is_ccw = turn_left(prev, curr, next)
+ for i in [1..points.length[ do
+ prev = curr
+ curr= next
+ next = points[i]
+ if turn_left(prev ,curr, next) != is_ccw then return false
end
return true
end
return projection
end
- # Is this polygon convex ?
+ # Remove `p` from the vertices, keeping at least 3 vertices
+ fun delete_vertex(p: Point[Float]) do
+ assert points.length > 3
+ points.remove(p)
+ end
+
+ # Does `self` intersects with `other`
+ fun intersects(other: APolygon): Bool is abstract
+
+ # Is `p` contained in `self` ?
+ fun contain(p: Point[Float]): Bool is abstract
+
+ # Add a vertex to `self`
+ fun add_vertex(p: Point[Float]): Bool do
+ points.add(p)
+ return true
+ end
+end
+
+# A simple polygon
+class Polygon
+ super APolygon
+ # TODO: implement algorithms for concave polygons ?
+end
+
+# Convex Polygon class
+class ConvexPolygon
+ super APolygon
+
+ # Does this polygon intersects `other` ?
#
# ~~~
# var p1 = new Point[Float](0.0, 0.0)
# var p3 = new Point[Float](0.0, 5.0)
# var p4 = new Point[Float](5.0, 5.0)
# var arr = new Array[Point[Float]].with_items(p1, p2, p3, p4)
- # var poly = new ConvexPolygon.with_vertices(arr)
+ # var poly = new ConvexPolygon(arr)
# poly.sort_ccw
- # assert poly.is_convex
+ # p1 = new Point[Float](2.5, 2.5)
+ # p2 = new Point[Float](7.5, 2.5)
+ # p3 = new Point[Float](2.5, 7.5)
+ # p4 = new Point[Float](7.5, 7.5)
+ # arr = new Array[Point[Float]].with_items(p1, p2, p3, p4)
+ # var poly2 = new ConvexPolygon(arr)
+ # poly2.sort_ccw
+ # assert poly.intersects(poly2)
# ~~~
- fun is_convex: Bool do
- var prev = points[points.length - 2]
- var curr = points[points.length - 1]
- var next = points[0]
- var is_ccw = turn_left(prev, curr, next)
- for i in [1..points.length[ do
- prev = curr
- curr= next
- next = points[i]
- if turn_left(prev ,curr, next) != is_ccw then return false
+ redef fun intersects(other) do
+ assert is_convex
+
+ var axes1 = axes
+ var axes2 = other.axes
+ for axis in axes1 do
+ var project1 = project(axis)
+ var project2 = other.project(axis)
+ if not project1.overlap(project2) then return false
+ end
+ for axis in axes2 do
+ var project1 = project(axis)
+ var project2 = other.project(axis)
+ if not project1.overlap(project2) then return false
end
return true
end
- # Check if `p` is in the polygon
- #
# ~~~
# var p1 = new Point[Float](0.0, 0.0)
# var p2 = new Point[Float](5.0, 0.0)
# var p4 = new Point[Float](5.0, 5.0)
# var p5 = new Point[Float](2.5, 2.5)
# var arr = new Array[Point[Float]].with_items(p1, p2, p3, p4)
- # var poly = new ConvexPolygon.with_vertices(arr)
+ # var poly = new ConvexPolygon(arr)
# poly.sort_ccw
# assert poly.contain(p5)
# ~~~
- fun contain(p : Point[Float]): Bool do
+ redef fun contain(p) do
var prev = points[points.length - 1]
var curr = p
var next = points[0]
# var p3 = new Point[Float](0.0, 5.0)
# var p4 = new Point[Float](5.0, 5.0)
# var arr = new Array[Point[Float]].with_items(p1, p2, p3, p4)
- # var poly = new ConvexPolygon.with_vertices(arr)
+ # var poly = new ConvexPolygon(arr)
# poly.sort_ccw
# assert poly.is_ccw
# ~~~
return not turn_left(prev, points[min_index], next)
end
- # Remove `p` from the vertices, keeping at least 3 vertices
- fun delete_vertex(p: Point[Float]) do
- if points.length > 3 then
- points.remove(p)
- end
- end
+
# Add a vertex to the polygon
#
# var p3 = new Point[Float](0.0, 5.0)
# var p4 = new Point[Float](5.0, 5.0)
# var arr = new Array[Point[Float]].with_items(p1, p2, p3, p4)
- # var poly = new ConvexPolygon.with_vertices(arr)
+ # var poly = new ConvexPolygon(arr)
# var p5 = new Point[Float](2.5, 7.5)
# assert poly.add_vertex(p5)
# ~~~
- fun add_vertex(p: Point[Float]): Bool do
+ redef fun add_vertex(p) do
assert points.length >= 3
var temp_list = points.clone
temp_list.add(p)
- var temp_polygon = new ConvexPolygon.with_vertices(temp_list)
+ var temp_polygon = new ConvexPolygon(temp_list)
temp_polygon.sort_ccw
if temp_polygon.is_convex then
points = temp_polygon.points
var min: Float is writable
var max: Float is writable
- fun overlap(other: Projection): Bool do
- return not (min > other.max or other.min > max)
- end
+ fun overlap(other: Projection): Bool do return not (min > other.max or other.min > max)
end
private class PointXCompare
redef type COMPARED: Point[Float]
- redef fun compare(a,b : COMPARED): Int do
+ redef fun compare(a,b) do
if a.x == b.x then
if a.y == b.y then return 0
if a.y > b.y then return - 1
end
end
+#TODO: CounterClockWise and ClockWise sorts are broken in some cases of concave polygons
+
# Sort the vertices of a polygon in counter clockwise order
private class CounterClockWiseSort
super PolygonSorter
- redef fun compare(a,b: COMPARED): Int do
+ redef fun compare(a,b) do
if a.x == b.x and a.y == b.y then return 0
if a.x - center.x >= 0.0 and b.x - center.x < 0.0 then return -1
if a.x - center.x < 0.0 and b.x - center.x >= 0.0 then return 1
- if a.x - center.x == 0.0 and b.x - center.x == 0 then
+ if a.x - center.x == 0.0 and b.x - center.x == 0.0 then
if a.y - center.y >= 0.0 or b.y - center.y >= 0.0 then
if a.y > b.y then return -1
return 1
private class ClockWiseSort
super PolygonSorter
- redef fun compare(a,b: COMPARED): Int do
+ redef fun compare(a,b) do
if a.x == b.x and a.y == b.y then return 0
if a.x - center.x >= 0.0 and b.x - center.x < 0.0 then return 1
if a.x - center.x < 0.0 and b.x - center.x >= 0.0 then return -1
end
end
-
# Get the convex hull of the set of `points`
#
# ~~~
pl1.remove_at(pl1.length - 1)
pl2.remove_at(pl2.length -1)
pl2.add_all(pl1)
- return new ConvexPolygon.with_vertices(pl2)
+ return new ConvexPolygon(pl2)
end
# Is the angle between [p1,p2] and [p2,p3] going left (counter clockwise) or right (clockwise) ?
fun turn_left(p1, p2, p3: Point[Float]): Bool do
return ((p2.x - p1.x) * (p3.y - p2.y) - (p3.x - p2.x) * (p2.y - p1.y)) > 0.0
end
+
+# Split a polygon into triangles
+# Useful for converting a concave polygon into multiple convex ones
+fun triangulate(pts: Array[Point[Float]], results: Array[ConvexPolygon]) do
+ var poly = new Polygon(pts)
+ poly.sort_ccw
+ pts = poly.points
+ recursive_triangulate(pts, results)
+end
+
+private fun recursive_triangulate(pts: Array[Point[Float]], results: Array[ConvexPolygon]) do
+ if pts.length == 3 then
+ results.add(new ConvexPolygon(pts))
+ return
+ end
+ var prev = pts[pts.length - 1]
+ var curr = pts[0]
+ var next = pts[1]
+ for i in [1..pts.length[ do
+ if turn_left(prev, curr, next) then
+ prev = pts[i-1]
+ curr = next
+ if i+1 == pts.length then next = pts[pts.length - 1] else next = pts[i+1]
+ continue
+ end
+ var contains = false
+ var triangle = new ConvexPolygon(new Array[Point[Float]].with_items(prev, curr, next))
+ for p in pts do
+ if p != prev and p != curr and p != next then
+ if triangle.contain(p) then
+ contains = true
+ break
+ end
+ end
+ end
+ if not contains then
+ results.add(triangle)
+ pts.remove(curr)
+ recursive_triangulate(pts, results)
+ break
+ end
+ prev = pts[i-1]
+ curr = next
+ if i+1 == pts.length then next = pts[pts.length - 1] else next = pts[i+1]
+ end
+end
private class DFAState0
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 8 then return null
if c <= 10 then return dfastate_1
if c <= 31 then return null
return null
end
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 8 then return null
if c <= 10 then return dfastate_1
if c <= 31 then return null
private class DFAState2
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 33 then return dfastate_2
if c <= 34 then return dfastate_29
if c <= 91 then return dfastate_2
private class DFAState4
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 47 then return null
if c <= 57 then return dfastate_5
return null
return t
end
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 45 then return null
if c <= 46 then return dfastate_24
if c <= 47 then return null
private class DFAState9
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 96 then return null
if c <= 97 then return dfastate_20
return null
private class DFAState10
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 116 then return null
if c <= 117 then return dfastate_17
return null
private class DFAState11
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 113 then return null
if c <= 114 then return dfastate_14
return null
private class DFAState14
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 116 then return null
if c <= 117 then return dfastate_15
return null
private class DFAState15
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 100 then return null
if c <= 101 then return dfastate_16
return null
private class DFAState17
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 107 then return null
if c <= 108 then return dfastate_18
return null
private class DFAState18
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 107 then return null
if c <= 108 then return dfastate_19
return null
private class DFAState20
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 107 then return null
if c <= 108 then return dfastate_21
return null
private class DFAState21
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 114 then return null
if c <= 115 then return dfastate_22
return null
private class DFAState22
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 100 then return null
if c <= 101 then return dfastate_23
return null
private class DFAState24
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 47 then return null
if c <= 57 then return dfastate_28
return null
private class DFAState25
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 42 then return null
if c <= 43 then return dfastate_26
if c <= 44 then return null
private class DFAState26
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 47 then return null
if c <= 57 then return dfastate_27
return null
return t
end
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 47 then return null
if c <= 57 then return dfastate_27
return null
return t
end
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 47 then return null
if c <= 57 then return dfastate_28
if c <= 68 then return null
private class DFAState30
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 33 then return null
if c <= 34 then return dfastate_2
if c <= 46 then return null
private class DFAState31
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 47 then return null
if c <= 57 then return dfastate_32
if c <= 64 then return null
private class DFAState32
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 47 then return null
if c <= 57 then return dfastate_33
if c <= 64 then return null
private class DFAState33
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 47 then return null
if c <= 57 then return dfastate_34
if c <= 64 then return null
private class DFAState34
super DFAState
redef fun trans(char) do
- var c = char.ascii
+ var c = char.code_point
if c <= 47 then return null
if c <= 57 then return dfastate_2
if c <= 64 then return null
buffer.append "\\\""
else if char == '\/' then
buffer.append "\\/"
- else if char < 16.ascii then
+ else if char < 16.code_point then
if char == '\n' then
buffer.append "\\n"
else if char == '\r' then
buffer.append "\\r"
else if char == '\t' then
buffer.append "\\t"
- else if char == 0x0C.ascii then
+ else if char == 0x0C.code_point then
buffer.append "\\f"
- else if char == 0x08.ascii then
+ else if char == 0x08.code_point then
buffer.append "\\b"
else
- buffer.append "\\u000{char.ascii.to_hex}"
+ buffer.append "\\u000{char.code_point.to_hex}"
end
else if char < ' ' then
- buffer.append "\\u00{char.ascii.to_hex}"
+ buffer.append "\\u00{char.code_point.to_hex}"
else
buffer.add char
end
i += 1
char = text[i]
if char == 'b' then
- char = 0x08.ascii
+ char = 0x08.code_point
else if char == 'f' then
- char = 0x0C.ascii
+ char = 0x0C.code_point
else if char == 'n' then
char = '\n'
else if char == 'r' then
if code >= 128 then
char = '?'
else
- char = code.ascii
+ char = code.code_point
end
i += 4
end
do
var str = number.to_s
for c in str.chars do
- var d = c.ascii-'0'.ascii
+ var d = c.code_point-'0'.code_point
assert d >= 0 and d <= 9
var img = imgs.imgs[d]
blit(img, x, y)
class OrderedTree[E: Object]
super Writable
super Collection[E]
+ super Cloneable
# The roots of the tree (in sequence)
var roots = new Array[E]
# For each element, the ordered array of its direct sub-elements.
var sub = new HashMap[E, Array[E]]
+ # The parent of each element.
+ #
+ # Roots have `null` as parent.
+ private var parents = new HashMap[E, nullable E]
+
+ redef fun length do return parents.length
+
+ redef fun has(e) do return parents.has_key(e)
+
+ # The parent of the element `e`
+ #
+ # Roots have `null` as parent.
+ #
+ # ~~~
+ # var tree = new OrderedTree[Int]
+ # tree.add(1, 2)
+ # assert tree.parent(2) == 1
+ # assert tree.parent(1) == null
+ # ~~~
+ fun parent(e: E): nullable E do return parents[e]
+
# Add a new element `e` in the tree.
+ #
# `p` is the parent of `e`.
- # if `p` is null, then `e` is a root element.
+ # If `p` is null, then `e` is a root element.
+ #
+ # If `e` is already in the tree, it is detached from its old
+ # parent and attached to the new parent `p`.
fun add(p: nullable E, e: E)
do
+ detach(e)
+ parents[e] = p
if p == null then
roots.add(e)
- else if sub.has_key(p) then
- sub[p].add(e)
else
- sub[p] = [e]
+ if not has(p) then add(null, p)
+ if sub.has_key(p) then
+ sub[p].add(e)
+ else
+ sub[p] = [e]
+ end
+ end
+ end
+
+ # Append all nodes `es` as children of `p`.
+ fun add_all(p: nullable E, es: Collection[E])
+ do
+ for e in es do add(p, e)
+ end
+
+ # Temporary remove `e`.
+ #
+ # Children of `e` are left untouched in the tree.
+ # This make the tree inconstant until `e` is added back.
+ private fun detach(e: E)
+ do
+ var old_parent = parents.get_or_null(e)
+ if old_parent != null then
+ var subs = sub[old_parent]
+ subs.remove(e)
+ if subs.is_empty then
+ # remove the sub when all children are detached
+ # so that `==` and `hash` are sane
+ # Otherwise an empty array will be considered
+ # differently than no array.
+ sub.keys.remove(old_parent)
+ end
+ else if roots.has(e) then
+ roots.remove(e)
end
end
do
if not sub.has_key(e) then return
var subs = sub[e]
+ if subs.is_empty then return
var last = subs.last
for e2 in subs do
if e2 != last then
# Order is preserved
#
# var tree = new OrderedTree[Int]
- # tree.add(null, 1)
- # tree.add(1, 11)
- # tree.add(11, 111)
- # tree.add(11, 112)
- # tree.add(1, 12)
- # tree.add(12, 121)
- # tree.add(12, 122)
- # tree.add(null, 2)
- # tree.add(2, 21)
- # tree.add(2, 22)
+ # tree.add_all(null, [1, 2])
+ # tree.add_all(1, [11, 12])
+ # tree.add_all(11, [111, 112])
+ # tree.add_all(12, [121, 122])
+ # tree.add_all(2, [21, 22])
# assert tree.to_a == [1, 11, 111, 112, 12, 121, 122, 2, 21, 22]
redef fun to_a: Array[E] do
var res = new Array[E]
redef fun first do return roots.first
# var tree = new OrderedTree[Int]
- # tree.add(null, 1)
- # tree.add(1, 11)
- # tree.add(11, 111)
- # tree.add(11, 112)
- # tree.add(1, 12)
- # tree.add(12, 121)
- # tree.add(12, 122)
- # tree.add(null, 2)
- # tree.add(2, 21)
- # tree.add(2, 22)
+ # tree.add_all(null, [1, 2])
+ # tree.add_all(1, [11, 12])
+ # tree.add_all(11, [111, 112])
+ # tree.add_all(12, [121, 122])
+ # tree.add_all(2, [21, 22])
# var order = [1, 11, 111, 112, 12, 121, 122, 2, 21, 22]
- # var res = new Array[Int]
- # for i in tree do res.add(i)
- # assert res == order
+ # assert tree.iterator.to_a == order
redef fun iterator do return new OrderedTreeIterator[E](self)
+
+ # Two trees are equal if they have the same nodes in the same order
+ #
+ # ~~~
+ # var t1 = new OrderedTree[Int]
+ # t1.add_all(null, [1, 2])
+ # t1.add_all(1, [11, 12])
+ #
+ # var t2 = new OrderedTree[Int]
+ # t2.add_all(null, [1, 2])
+ #
+ # assert t1 != t2
+ #
+ # t2.add_all(1, [11, 12])
+ #
+ # assert t1 == t2
+ # ~~~
+ redef fun ==(other)
+ do
+ if not other isa OrderedTree[Object] then return false
+ return roots == other.roots and sub == other.sub
+ end
+
+ redef fun hash
+ do
+ return roots.hash + sub.hash
+ end
+
+ # Shallow clone of the tree.
+ #
+ # ~~~
+ # var t = new OrderedTree[Int]
+ # t.add_all(null, [1, 2])
+ # t.add_all(1, [11, 12])
+ #
+ # assert t.clone == t
+ # ~~~
+ redef fun clone
+ do
+ var res = new OrderedTree[E]
+ res.add_all(null, roots)
+ for p, es in sub do
+ res.add_all(p, es)
+ end
+ return res
+ end
end
# An Iterator over an OrderedTree
# read the next byte. Else, return `-1`.
fun expect_delimiter: Int do
if accept('"') then
- return '"'.ascii
+ return '"'.code_point
else if accept('\'') then
- return '\''.ascii
+ return '\''.code_point
else
fire_unexpected_char(". Expecting `\"` or `'`")
return -1
# If the last read byte is forbidden, fire a fatal error instead.
fun expect_xml_char(buffer: Buffer): Bool do
if is_xml_char then
- buffer.chars.push(last_char.ascii)
+ buffer.chars.push(last_char.code_point)
read_char
return true
else if eof then
buffer.chars.push(' ')
read_char
return true
- else if last_char == '<'.ascii then
+ else if last_char == '<'.code_point then
return fire_fatal_error("`<` is forbidden in attribute values.")
else
return expect_xml_char(buffer)
# Is the last read byte matches the `NameStartChar` production?
fun is_name_start_char: Bool do
# TODO: Handle code points above 0x7F.
- return ['A'.ascii .. 'Z'.ascii].has(last_char) or
- ['a'.ascii .. 'z'.ascii].has(last_char) or
- last_char == '_'.ascii or
- last_char == ':'.ascii or
+ return ['A'.code_point .. 'Z'.code_point].has(last_char) or
+ ['a'.code_point .. 'z'.code_point].has(last_char) or
+ last_char == '_'.code_point or
+ last_char == ':'.code_point or
last_char > 127
end
fun is_name_char: Bool do
# TODO: Handle code points above 0x7F.
return is_name_start_char or
- last_char == '-'.ascii or
- last_char == '.'.ascii or
+ last_char == '-'.code_point or
+ last_char == '.'.code_point or
is_digit
end
if not is_name_start_char then
return fire_unexpected_char(" at the beginning of a name")
end
- buffer.chars.push(last_char.ascii)
+ buffer.chars.push(last_char.code_point)
read_char
while is_name_char do
- buffer.chars.push(last_char.ascii)
+ buffer.chars.push(last_char.code_point)
read_char
end
return true
# Is the last read byte matches the `[0-9]` production?
fun is_digit: Bool do
- return ['0'.ascii .. '9'.ascii].has(last_char)
+ return ['0'.code_point .. '9'.code_point].has(last_char)
end
# Accept a `[0-9]+` token.
fun accept_digits(buffer: Buffer): Bool do
if is_digit then
loop
- buffer.chars.push(last_char.ascii)
+ buffer.chars.push(last_char.code_point)
read_char
if not is_digit then return true
end
# Is `last_char` matches the `[0-9a-fA-F]` production?
fun is_hex: Bool do
- return ['0'.ascii .. '9'.ascii].has(last_char) or
- ['A'.ascii .. 'Z'.ascii].has(last_char) or
- ['a'.ascii .. 'Z'.ascii].has(last_char)
+ return ['0'.code_point .. '9'.code_point].has(last_char) or
+ ['A'.code_point .. 'Z'.code_point].has(last_char) or
+ ['a'.code_point .. 'Z'.code_point].has(last_char)
end
# Expect a `[0-9a-fA-F]+` token.
fun expect_hex(buffer: Buffer): Bool do
if is_hex then
loop
- buffer.chars.push(last_char.ascii)
+ buffer.chars.push(last_char.code_point)
read_char
if not is_hex then return true
end
else if last_char < 0 then
fire_fatal_error("Internal error: Already at the end of the file.")
return
- else if last_char == '\n'.ascii then
+ else if last_char == '\n'.code_point then
locator.line_number += 1
locator.column_number = 1
else
# XML 1.0 end-of-line handling
# Note: Regardless the XML version, any EOL defined by the
# recommandation MUST be reported as a single LINE FEED.
- if was_cr and last_char == '\n'.ascii then
+ if was_cr and last_char == '\n'.code_point then
# EOL already reported. => Skip this byte.
s = input.read_byte
if s == null then
last_char = s.to_i
end
end
- was_cr = last_char == '\r'.ascii
+ was_cr = last_char == '\r'.code_point
if was_cr then
# Regardless the following byte, '\r' always introduce an EOL.
- last_char = '\n'.ascii
+ last_char = '\n'.code_point
end
end
fun is_int(c: Int): Bool do return last_char == c
# Does the last read byte equal `c`?
- fun is_char(c: Char): Bool do return last_char == c.ascii
+ fun is_char(c: Char): Bool do return last_char == c.code_point
# Expect the specified byte.
fun accept_int(expected: Int): Bool do
# Accept the specified byte.
fun accept(expected: Char): Bool do
- return accept_int(expected.ascii)
+ return accept_int(expected.code_point)
end
# Ensure the last read byte is equal to `expected`.
# Return `true` if and only if the last read byte as the expected value.
fun expect_int(expected: Int, context: String): Bool do
return accept_int(expected) or
- fire_unexpected_char("{context}. Expecting `{expected.ascii}`.")
+ fire_unexpected_char("{context}. Expecting `{expected.code_point}`.")
end
# Ensure the last read byte is equal to `expected`.
if not accept(chars[i]) then
if is_xml_char then
return fire_fatal_error("Unexpected " +
- "`{expected.substring(0, i)}{last_char.ascii.to_s}`" +
+ "`{expected.substring(0, i)}{last_char.code_point.to_s}`" +
"{context}. Expecting `{expected}`.")
else if eof then
return fire_fatal_error("Unexpected end of file{context}. " +
# Return `false`.
fun fire_unexpected_char(rest_of_message: String): Bool do
if is_xml_char then
- return fire_fatal_error("Unexpected character `{last_char.ascii.to_s}`{rest_of_message}.")
+ return fire_fatal_error("Unexpected character `{last_char.code_point.to_s}`{rest_of_message}.")
else if eof then
return fire_fatal_error("Unexpected end of file{rest_of_message}.")
else
if lexer.accept('#') then
if lexer.accept('x') then
if lexer.expect_hex(ref) then
- buffer.chars.add(ref.to_hex.ascii)
+ buffer.chars.add(ref.to_hex.code_point)
return lexer.expect(';', "")
else
return lexer.fire_unexpected_char(
". Expecting an hexadecimal digit")
end
else if lexer.accept_digits(ref) then
- buffer.chars.add(ref.to_i.ascii)
+ buffer.chars.add(ref.to_i.code_point)
return lexer.expect(';', "")
else
return lexer.fire_unexpected_char(" in a character reference. " +
--- /dev/null
+[package]
+name=text_stat
+tags=debug,lib
+maintainer=Lucas Bajolet <r4pass@hotmail.com>
+license=Apache-2.0
+[upstream]
+browse=https://github.com/nitlang/nit/tree/master/lib/text_stat.nit
+git=https://github.com/nitlang/nit.git
+git.directory=lib/text_stat.nit
+homepage=http://nitlanguage.org
+issues=https://github.com/nitlang/nit/issues
" Keywords
syn keyword NITKeyword abstract intern new
syn keyword NITDefine private public protected intrude readable writable redef
-syn keyword NITControl if while for assert and or in as isa once break continue return abort
+syn keyword NITControl if while for with assert and or in as isa once break continue return abort
syn keyword NITClass nullable
syn keyword NITInclude special
syn keyword NITTodo FIXME NOTE TODO XXX contained
do
var t = mmodule.char_type
- if value.ascii < 128 then
+ if value.code_point < 128 then
return new RuntimeVariable("'{value.to_s.escape_to_c}'", t, t)
else
- return new RuntimeVariable("{value.ascii}", t, t)
+ return new RuntimeVariable("{value.code_point}", t, t)
end
end
else if pname == "to_b" then
v.ret(v.new_expr("(unsigned char){arguments[0]}", ret.as(not null)))
return true
- else if pname == "ascii" then
- v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
- return true
end
else if cname == "Char" then
if pname == "object_id" then
else if pname == "to_i" then
v.ret(v.new_expr("{arguments[0]}-'0'", ret.as(not null)))
return true
- else if pname == "ascii" then
- v.ret(v.new_expr("(long){arguments[0]}", ret.as(not null)))
- return true
end
else if cname == "Byte" then
if pname == "output" then
else if pname == "to_u32" then
v.ret(v.new_expr("(uint32_t){arguments[0]}", ret.as(not null)))
return true
- else if pname == "ascii" then
- v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
- return true
end
else if cname == "Bool" then
if pname == "output" then
else if pname == "to_f" then
v.ret(v.new_expr("(double){arguments[0]}", ret.as(not null)))
return true
- else if pname == "ascii" then
- v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
- return true
else if pname == "&" then
v.ret(v.new_expr("{arguments[0]} & {arguments[1]}", ret.as(not null)))
return true
else if pname == "unary ~" then
v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
return true
- else if pname == "ascii" then
- v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
- return true
end
else if cname == "UInt16" then
if pname == "output" then
else if pname == "unary ~" then
v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
return true
- else if pname == "ascii" then
- v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
- return true
end
else if cname == "Int32" then
if pname == "output" then
else if pname == "unary ~" then
v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
return true
- else if pname == "ascii" then
- v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
- return true
end
else if cname == "UInt32" then
if pname == "output" then
else if pname == "unary ~" then
v.ret(v.new_expr("~{arguments[0]}", ret.as(not null)))
return true
- else if pname == "ascii" then
- v.ret(v.new_expr("{arguments[0]}", ret.as(not null)))
- return true
end
end
if pname == "exit" then
# use some Huffman coding.
if t.name == "Int" then
class_info[1] = t
+ t.mclass_type.tag_value = 1
else if t.name == "Char" then
class_info[2] = t
+ t.mclass_type.tag_value = 2
else if t.name == "Bool" then
class_info[3] = t
+ t.mclass_type.tag_value = 3
else
continue
end
else
var mtype1 = value1.mtype.as(MClassType)
self.require_declaration("class_{mtype1.c_name}")
- self.add("{res} = ({value2} != NULL) && ({value2}->class == &class_{mtype1.c_name}); /* is_same_type_test */")
+ self.add("{res} = ({value2} != NULL) && ({class_info(value2)} == &class_{mtype1.c_name}); /* is_same_type_test */")
end
else
self.add("{res} = ({value1} == {value2}) || ({value1} != NULL && {value2} != NULL && {class_info(value1)} == {class_info(value2)}); /* is_same_type_test */")
value2 = tmp
end
if value1.mtype.is_c_primitive then
- if value2.mtype == value1.mtype then
+ var t1 = value1.mtype
+ assert t1 == value1.mcasttype
+
+ # Fast case: same C type.
+ if value2.mtype == t1 then
+ # Same exact C primitive representation.
self.add("{res} = {value1} == {value2};")
- else if value2.mtype.is_c_primitive then
- self.add("{res} = 0; /* incompatible types {value1.mtype} vs. {value2.mtype}*/")
- else if value1.mtype.is_tagged then
- self.add("{res} = ({value2} != NULL) && ({self.autobox(value2, value1.mtype)} == {value1});")
+ return res
+ end
+
+ # Complex case: value2 has a different representation
+ # Thus, it should be checked if `value2` is type-compatible with `value1`
+ # This compatibility is done statically if possible and dynamically else
+
+ # Conjunction (ands) of dynamic tests according to the static knowledge
+ var tests = new Array[String]
+
+ var t2 = value2.mcasttype
+ if t2 isa MNullableType then
+ # The destination type cannot be null
+ tests.add("({value2} != NULL)")
+ t2 = t2.mtype
+ else if t2 isa MNullType then
+ # `value2` is known to be null, thus incompatible with a primitive
+ self.add("{res} = 0; /* incompatible types {t1} vs. {t2}*/")
+ return res
+ end
+
+ if t2 == t1 then
+ # Same type but different representation.
+ else if t2.is_c_primitive then
+ # Type of `value2` is a different primitive type, thus incompatible
+ self.add("{res} = 0; /* incompatible types {t1} vs. {t2}*/")
+ return res
+ else if t1.is_tagged then
+ # To be equal, `value2` should also be correctly tagged
+ tests.add("({extract_tag(value2)} == {t1.tag_value})")
else
- var mtype1 = value1.mtype.as(MClassType)
- self.require_declaration("class_{mtype1.c_name}")
- self.add("{res} = ({value2} != NULL) && ({value2}->class == &class_{mtype1.c_name});")
- self.add("if ({res}) \{")
- self.add("{res} = ({self.autobox(value2, value1.mtype)} == {value1});")
- self.add("\}")
+ # To be equal, `value2` should also be boxed with the same class
+ self.require_declaration("class_{t1.c_name}")
+ tests.add "({class_info(value2)} == &class_{t1.c_name})"
end
+
+ # Compare the unboxed `value2` with `value1`
+ if tests.not_empty then
+ self.add "if ({tests.join(" && ")}) \{"
+ end
+ self.add "{res} = {self.autobox(value2, t1)} == {value1};"
+ if tests.not_empty then
+ self.add "\} else {res} = 0;"
+ end
+
return res
end
var maybe_null = true
# Are values of `self` tagged?
# If false, it means that the type is not primitive, or is boxed.
var is_tagged = false
+
+ # The tag value of the type
+ #
+ # ENSURE `is_tagged == (tag_value > 0)`
+ # ENSURE `not is_tagged == (tag_value == 0)`
+ var tag_value = 0
end
redef class MEntity
b.append("\\\\")
else if c == '`' then
b.append("'")
- else if c.ascii < 32 then
- b.append("\\{c.ascii.to_base(8, false)}")
+ else if c.code_point < 32 then
+ b.append("\\{c.code_point.to_base(8, false)}")
else
b.add(c)
end
return v.bool_instance(recvval >= args[1].to_i)
else if pname == "<=>" then
return v.int_instance(recvval <=> args[1].to_i)
- else if pname == "ascii" then
- return v.char_instance(recvval.ascii)
else if pname == "to_f" then
return v.float_instance(recvval.to_f)
else if pname == "to_b" then
end
else if cname == "Char" then
var recv = args[0].val.as(Char)
- if pname == "ascii" then
- return v.int_instance(recv.ascii)
- else if pname == "successor" then
+ if pname == "successor" then
return v.char_instance(recv.successor(args[1].to_i))
else if pname == "predecessor" then
return v.char_instance(recv.predecessor(args[1].to_i))
fun identify_file(path: String): nullable ModulePath
do
# special case for not a nit file
- if path.file_extension != "nit" then
+ if not path.has_suffix(".nit") then
# search dirless files in known -I paths
if not path.chars.has('/') then
var res = search_module_in_paths(null, path, self.paths)
end
# Fast track, the path is already known
- var pn = path.basename(".nit")
+ if identified_files_by_path.has_key(path) then return identified_files_by_path[path]
var rp = module_absolute_path(path)
if identified_files_by_path.has_key(rp) then return identified_files_by_path[rp]
+ var pn = path.basename(".nit")
+
# Search for a group
var mgrouppath = path.join_path("..").simplify_path
var mgroup = get_mgroup(mgrouppath)
mgroup.module_paths.add(res)
identified_files_by_path[rp] = res
+ identified_files_by_path[path] = res
identified_files.add(res)
return res
end
# Note: `paths` is also used to look for mgroups
fun get_mgroup(dirpath: String): nullable MGroup
do
- if not dirpath.file_exists then do
+ var stat = dirpath.file_stat
+
+ if stat == null then do
+ # search dirless directories in known -I paths
+ if dirpath.chars.has('/') then return null
for p in paths do
var try = p / dirpath
- if try.file_exists then
+ stat = try.file_stat
+ if stat != null then
dirpath = try
break label
end
return null
end label
+ # Filter out non-directories
+ if not stat.is_dir then
+ return null
+ end
+
+ # Fast track, the path is already known
var rdp = module_absolute_path(dirpath)
if mgroups.has_key(rdp) then
return mgroups[rdp]
end
- # Filter out non-directories
- var stat = dirpath.file_stat
- if stat == null or not stat.is_dir then
- mgroups[rdp] = null
- return null
- end
-
# By default, the name of the package or group is the base_name of the directory
- var pn = rdp.basename(".nit")
+ var pn = rdp.basename
# Check `package.ini` that indicate a package
var ini = null
var fp = p/f
var g = get_mgroup(fp)
# Recursively scan for groups of the same package
- if g != null and g.mpackage == mgroup.mpackage then
+ if g == null then
+ identify_file(fp)
+ else if g.mpackage == mgroup.mpackage then
scan_group(g)
end
- identify_file(fp)
end
end
# Transform relative paths (starting with '../') into absolute paths
private fun module_absolute_path(path: String): String do
- return getcwd.join_path(path).simplify_path
+ return path.realpath
end
# Try to load a module AST using a path.
# Display an error if there is a problem (IO / lexer / parser) and return null
fun load_module_ast(filename: String): nullable AModule
do
- if filename.file_extension != "nit" then
+ if not filename.has_suffix(".nit") then
self.toolcontext.error(null, "Error: file `{filename}` is not a valid nit module.")
return null
end
# * `"0;32"` for green
fun colored_line(color: String): String
do
- var esc = 27.ascii
+ var esc = 27.code_point
var def = "{esc}[0m"
var col = "{esc}[{color}m"
# This does not corrupt the lexer and works perfectly on any character.
#
# TL;DR: Java fucked up, need retarded solution to cope for retarded decision
- var c = string[sp].ascii
+ var c = string[sp].code_point
if c >= 256 then c = 255
sp += 1
# A colored version of the message including the original source line
fun to_color_string: String
do
- var esc = 27.ascii
+ var esc = 27.code_point
#var red = "{esc}[0;31m"
#var bred = "{esc}[1;31m"
#var green = "{esc}[0;32m"
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+var i = 1
+var b = true
+var f = 1u8
+var ni: nullable Int = 1
+var nb: nullable Bool = true
+var nf: nullable Byte = 1u8
+var oi: nullable Object = 1
+var ob: nullable Object = true
+var of: nullable Object = 1u8
+
+
+(i == i).output
+(b == i).output
+(f == i).output
+
+'\n'.output
+
+(i == ni).output
+(b == ni).output
+(f == ni).output
+
+'\n'.output
+
+(i == oi).output
+(b == oi).output
+(f == oi).output
+
+'\n'.output
+'\n'.output
+
+(ni == i).output
+(nb == i).output
+(nf == i).output
+
+'\n'.output
+
+(ni == ni).output
+(nb == ni).output
+(nf == ni).output
+
+'\n'.output
+
+(ni == oi).output
+(nb == oi).output
+(nf == oi).output
+
+'\n'.output
+'\n'.output
+
+(oi == i).output
+(ob == i).output
+(of == i).output
+
+'\n'.output
+
+(oi == ni).output
+(ob == ni).output
+(of == ni).output
+
+'\n'.output
+
+(oi == oi).output
+(ob == oi).output
+(of == oi).output
+
+'\n'.output
+'\n'.output
+'\n'.output
+
+(i == b).output
+(b == b).output
+(f == b).output
+
+'\n'.output
+
+(i == nb).output
+(b == nb).output
+(f == nb).output
+
+'\n'.output
+
+(i == ob).output
+(b == ob).output
+(f == ob).output
+
+'\n'.output
+'\n'.output
+
+(ni == b).output
+(nb == b).output
+(nf == b).output
+
+'\n'.output
+
+(ni == nb).output
+(nb == nb).output
+(nf == nb).output
+
+'\n'.output
+
+(ni == ob).output
+(nb == ob).output
+(nf == ob).output
+
+'\n'.output
+'\n'.output
+
+(oi == b).output
+(ob == b).output
+(of == b).output
+
+'\n'.output
+
+(oi == nb).output
+(ob == nb).output
+(of == nb).output
+
+'\n'.output
+
+(oi == ob).output
+(ob == ob).output
+(of == ob).output
+
+'\n'.output
+'\n'.output
+'\n'.output
+
+(i == f).output
+(b == f).output
+(f == f).output
+
+'\n'.output
+
+(i == nf).output
+(b == nf).output
+(f == nf).output
+
+'\n'.output
+
+(i == of).output
+(b == of).output
+(f == of).output
+
+'\n'.output
+'\n'.output
+
+(ni == f).output
+(nb == f).output
+(nf == f).output
+
+'\n'.output
+
+(ni == nf).output
+(nb == nf).output
+(nf == nf).output
+
+'\n'.output
+
+(ni == of).output
+(nb == of).output
+(nf == of).output
+
+'\n'.output
+'\n'.output
+
+(oi == f).output
+(ob == f).output
+(of == f).output
+
+'\n'.output
+
+(oi == nf).output
+(ob == nf).output
+(of == nf).output
+
+'\n'.output
+
+(oi == of).output
+(ob == of).output
+(of == of).output
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+var i = 1
+var b = true
+var f = 1u8
+var ni: nullable Int = 1
+var nb: nullable Bool = true
+var nf: nullable Byte = 1u8
+var oi: nullable Object = 1
+var ob: nullable Object = true
+var of: nullable Object = 1u8
+
+
+(i.is_same_instance(i)).output
+(b.is_same_instance(i)).output
+(f.is_same_instance(i)).output
+
+'\n'.output
+
+(i.is_same_instance(ni)).output
+(b.is_same_instance(ni)).output
+(f.is_same_instance(ni)).output
+
+'\n'.output
+
+(i.is_same_instance(oi)).output
+(b.is_same_instance(oi)).output
+(f.is_same_instance(oi)).output
+
+'\n'.output
+'\n'.output
+
+(ni.is_same_instance(i)).output
+(nb.is_same_instance(i)).output
+(nf.is_same_instance(i)).output
+
+'\n'.output
+
+(ni.is_same_instance(ni)).output
+(nb.is_same_instance(ni)).output
+(nf.is_same_instance(ni)).output
+
+'\n'.output
+
+(ni.is_same_instance(oi)).output
+(nb.is_same_instance(oi)).output
+(nf.is_same_instance(oi)).output
+
+'\n'.output
+'\n'.output
+
+(oi.is_same_instance(i)).output
+(ob.is_same_instance(i)).output
+(of.is_same_instance(i)).output
+
+'\n'.output
+
+(oi.is_same_instance(ni)).output
+(ob.is_same_instance(ni)).output
+(of.is_same_instance(ni)).output
+
+'\n'.output
+
+(oi.is_same_instance(oi)).output
+(ob.is_same_instance(oi)).output
+(of.is_same_instance(oi)).output
+
+'\n'.output
+'\n'.output
+'\n'.output
+
+(i.is_same_instance(b)).output
+(b.is_same_instance(b)).output
+(f.is_same_instance(b)).output
+
+'\n'.output
+
+(i.is_same_instance(nb)).output
+(b.is_same_instance(nb)).output
+(f.is_same_instance(nb)).output
+
+'\n'.output
+
+(i.is_same_instance(ob)).output
+(b.is_same_instance(ob)).output
+(f.is_same_instance(ob)).output
+
+'\n'.output
+'\n'.output
+
+(ni.is_same_instance(b)).output
+(nb.is_same_instance(b)).output
+(nf.is_same_instance(b)).output
+
+'\n'.output
+
+(ni.is_same_instance(nb)).output
+(nb.is_same_instance(nb)).output
+(nf.is_same_instance(nb)).output
+
+'\n'.output
+
+(ni.is_same_instance(ob)).output
+(nb.is_same_instance(ob)).output
+(nf.is_same_instance(ob)).output
+
+'\n'.output
+'\n'.output
+
+(oi.is_same_instance(b)).output
+(ob.is_same_instance(b)).output
+(of.is_same_instance(b)).output
+
+'\n'.output
+
+(oi.is_same_instance(nb)).output
+(ob.is_same_instance(nb)).output
+(of.is_same_instance(nb)).output
+
+'\n'.output
+
+(oi.is_same_instance(ob)).output
+(ob.is_same_instance(ob)).output
+(of.is_same_instance(ob)).output
+
+'\n'.output
+'\n'.output
+'\n'.output
+
+(i.is_same_instance(f)).output
+(b.is_same_instance(f)).output
+(f.is_same_instance(f)).output
+
+'\n'.output
+
+(i.is_same_instance(nf)).output
+(b.is_same_instance(nf)).output
+(f.is_same_instance(nf)).output
+
+'\n'.output
+
+(i.is_same_instance(of)).output
+(b.is_same_instance(of)).output
+(f.is_same_instance(of)).output
+
+'\n'.output
+'\n'.output
+
+(ni.is_same_instance(f)).output
+(nb.is_same_instance(f)).output
+(nf.is_same_instance(f)).output
+
+'\n'.output
+
+(ni.is_same_instance(nf)).output
+(nb.is_same_instance(nf)).output
+(nf.is_same_instance(nf)).output
+
+'\n'.output
+
+(ni.is_same_instance(of)).output
+(nb.is_same_instance(of)).output
+(nf.is_same_instance(of)).output
+
+'\n'.output
+'\n'.output
+
+(oi.is_same_instance(f)).output
+(ob.is_same_instance(f)).output
+(of.is_same_instance(f)).output
+
+'\n'.output
+
+(oi.is_same_instance(nf)).output
+(ob.is_same_instance(nf)).output
+(of.is_same_instance(nf)).output
+
+'\n'.output
+
+(oi.is_same_instance(of)).output
+(ob.is_same_instance(of)).output
+(of.is_same_instance(of)).output
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+var i = 1
+var b = true
+var f = 1u8
+var ni: Int = 0
+var nb: Bool = false
+var nf: Byte = 0u8
+var oi: Object = 1
+var ob: Object = true
+var of: Object = 1u8
+
+
+(i.is_same_type(i)).output
+(b.is_same_type(i)).output
+(f.is_same_type(i)).output
+
+'\n'.output
+
+(i.is_same_type(ni)).output
+(b.is_same_type(ni)).output
+(f.is_same_type(ni)).output
+
+'\n'.output
+
+(i.is_same_type(oi)).output
+(b.is_same_type(oi)).output
+(f.is_same_type(oi)).output
+
+'\n'.output
+'\n'.output
+
+(ni.is_same_type(i)).output
+(nb.is_same_type(i)).output
+(nf.is_same_type(i)).output
+
+'\n'.output
+
+(ni.is_same_type(ni)).output
+(nb.is_same_type(ni)).output
+(nf.is_same_type(ni)).output
+
+'\n'.output
+
+(ni.is_same_type(oi)).output
+(nb.is_same_type(oi)).output
+(nf.is_same_type(oi)).output
+
+'\n'.output
+'\n'.output
+
+(oi.is_same_type(i)).output
+(ob.is_same_type(i)).output
+(of.is_same_type(i)).output
+
+'\n'.output
+
+(oi.is_same_type(ni)).output
+(ob.is_same_type(ni)).output
+(of.is_same_type(ni)).output
+
+'\n'.output
+
+(oi.is_same_type(oi)).output
+(ob.is_same_type(oi)).output
+(of.is_same_type(oi)).output
+
+'\n'.output
+'\n'.output
+'\n'.output
+
+(i.is_same_type(b)).output
+(b.is_same_type(b)).output
+(f.is_same_type(b)).output
+
+'\n'.output
+
+(i.is_same_type(nb)).output
+(b.is_same_type(nb)).output
+(f.is_same_type(nb)).output
+
+'\n'.output
+
+(i.is_same_type(ob)).output
+(b.is_same_type(ob)).output
+(f.is_same_type(ob)).output
+
+'\n'.output
+'\n'.output
+
+(ni.is_same_type(b)).output
+(nb.is_same_type(b)).output
+(nf.is_same_type(b)).output
+
+'\n'.output
+
+(ni.is_same_type(nb)).output
+(nb.is_same_type(nb)).output
+(nf.is_same_type(nb)).output
+
+'\n'.output
+
+(ni.is_same_type(ob)).output
+(nb.is_same_type(ob)).output
+(nf.is_same_type(ob)).output
+
+'\n'.output
+'\n'.output
+
+(oi.is_same_type(b)).output
+(ob.is_same_type(b)).output
+(of.is_same_type(b)).output
+
+'\n'.output
+
+(oi.is_same_type(nb)).output
+(ob.is_same_type(nb)).output
+(of.is_same_type(nb)).output
+
+'\n'.output
+
+(oi.is_same_type(ob)).output
+(ob.is_same_type(ob)).output
+(of.is_same_type(ob)).output
+
+'\n'.output
+'\n'.output
+'\n'.output
+
+(i.is_same_type(f)).output
+(b.is_same_type(f)).output
+(f.is_same_type(f)).output
+
+'\n'.output
+
+(i.is_same_type(nf)).output
+(b.is_same_type(nf)).output
+(f.is_same_type(nf)).output
+
+'\n'.output
+
+(i.is_same_type(of)).output
+(b.is_same_type(of)).output
+(f.is_same_type(of)).output
+
+'\n'.output
+'\n'.output
+
+(ni.is_same_type(f)).output
+(nb.is_same_type(f)).output
+(nf.is_same_type(f)).output
+
+'\n'.output
+
+(ni.is_same_type(nf)).output
+(nb.is_same_type(nf)).output
+(nf.is_same_type(nf)).output
+
+'\n'.output
+
+(ni.is_same_type(of)).output
+(nb.is_same_type(of)).output
+(nf.is_same_type(of)).output
+
+'\n'.output
+'\n'.output
+
+(oi.is_same_type(f)).output
+(ob.is_same_type(f)).output
+(of.is_same_type(f)).output
+
+'\n'.output
+
+(oi.is_same_type(nf)).output
+(ob.is_same_type(nf)).output
+(of.is_same_type(nf)).output
+
+'\n'.output
+
+(oi.is_same_type(of)).output
+(ob.is_same_type(of)).output
+(of.is_same_type(of)).output
o = _c
(o == null).output
(not o == '\0').output
- #alt3#_c.ascii.output
+ #alt3#_c.code_point.output
end
end
--- /dev/null
+true
+false
+false
+
+true
+false
+false
+
+true
+false
+false
+
+
+true
+false
+false
+
+true
+false
+false
+
+true
+false
+false
+
+
+true
+false
+false
+
+true
+false
+false
+
+true
+false
+false
+
+
+
+false
+true
+false
+
+false
+true
+false
+
+false
+true
+false
+
+
+false
+true
+false
+
+false
+true
+false
+
+false
+true
+false
+
+
+false
+true
+false
+
+false
+true
+false
+
+false
+true
+false
+
+
+
+false
+false
+true
+
+false
+false
+true
+
+false
+false
+true
+
+
+false
+false
+true
+
+false
+false
+true
+
+false
+false
+true
+
+
+false
+false
+true
+
+false
+false
+true
+
+false
+false
+true
--- /dev/null
+true
+false
+false
+
+true
+false
+false
+
+true
+false
+false
+
+
+true
+false
+false
+
+true
+false
+false
+
+true
+false
+false
+
+
+true
+false
+false
+
+true
+false
+false
+
+true
+false
+false
+
+
+
+false
+true
+false
+
+false
+true
+false
+
+false
+true
+false
+
+
+false
+true
+false
+
+false
+true
+false
+
+false
+true
+false
+
+
+false
+true
+false
+
+false
+true
+false
+
+false
+true
+false
+
+
+
+false
+false
+true
+
+false
+false
+true
+
+false
+false
+true
+
+
+false
+false
+true
+
+false
+false
+true
+
+false
+false
+true
+
+
+false
+false
+true
+
+false
+false
+true
+
+false
+false
+true
--- /dev/null
+true
+false
+false
+
+true
+false
+false
+
+true
+false
+false
+
+
+true
+false
+false
+
+true
+false
+false
+
+true
+false
+false
+
+
+true
+false
+false
+
+true
+false
+false
+
+true
+false
+false
+
+
+
+false
+true
+false
+
+false
+true
+false
+
+false
+true
+false
+
+
+false
+true
+false
+
+false
+true
+false
+
+false
+true
+false
+
+
+false
+true
+false
+
+false
+true
+false
+
+false
+true
+false
+
+
+
+false
+false
+true
+
+false
+false
+true
+
+false
+false
+true
+
+
+false
+false
+true
+
+false
+false
+true
+
+false
+false
+true
+
+
+false
+false
+true
+
+false
+false
+true
+
+false
+false
+true
../lib/core/kernel.nit:431,1--486,3: Error: `kernel#Numeric` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
../lib/core/kernel.nit:492,1--515,3: Error: `kernel#Bool` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
../lib/core/kernel.nit:517,1--599,3: Error: `kernel#Float` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
-../lib/core/kernel.nit:601,1--697,3: Error: `kernel#Byte` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
-../lib/core/kernel.nit:699,1--884,3: Error: `kernel#Int` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
-../lib/core/kernel.nit:886,1--1039,3: Error: `kernel#Char` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
-../lib/core/kernel.nit:1041,1--1048,3: Error: `kernel#Pointer` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+../lib/core/kernel.nit:601,1--702,3: Error: `kernel#Byte` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+../lib/core/kernel.nit:704,1--890,3: Error: `kernel#Int` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+../lib/core/kernel.nit:892,1--1060,3: Error: `kernel#Char` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
+../lib/core/kernel.nit:1062,1--1069,3: Error: `kernel#Pointer` does not specialize `module_0#Object`. Possible duplication of the root class `Object`?
-Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:720)
+Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:725)
11
21
31
-Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:720)
+Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:725)
11
21
31
-Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:720)
+Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:725)
11
21
31
`--subdir (\e[33mproject1/subdir\e[m)
|--\e[1mmodule4\e[m (\e[33mproject1/subdir/module4.nit\e[m)
`--\e[1mmodule_0\e[m (\e[33mproject1/subdir/module_0.nit\e[m)
-\e[1mproject2\e[m (\e[33mproject1/project2/project2.nit\e[m)
`--subdir (\e[33mproject1/subdir\e[m)
|--\e[1mmodule4\e[m (\e[33mproject1/subdir/module4.nit\e[m)
`--\e[1mmodule_0\e[m (\e[33mproject1/subdir/module_0.nit\e[m)
-\e[1mproject2\e[m (\e[33mproject1/project2/project2.nit\e[m)
project1/\e[1mmodule_01\e[m (\e[33mproject1/module_01.nit\e[m)
project1/\e[1mmodule_02\e[m (\e[33mproject1/module_02.nit\e[m)
project1/\e[1mproject1\e[m (\e[33mproject1/project1.nit\e[m)
-project2/\e[1mproject2\e[m (\e[33mproject1/project2/project2.nit\e[m)
Numeric -> Float [dir=back arrowtail=open style=dashed];
Byte [
- label = "{Byte||+ %(i: Byte): Byte\l+ \<\<(i: Int): Byte\l+ \>\>(i: Int): Byte\l}"
+ label = "{Byte||+ %(i: Byte): Byte\l+ \<\<(i: Int): Byte\l+ \>\>(i: Int): Byte\l+ ascii(): Char\l}"
]
Discrete -> Byte [dir=back arrowtail=open style=dashed];
Numeric -> Byte [dir=back arrowtail=open style=dashed];
Int [
- label = "{Int||+ %(i: Int): Int\l+ \<\<(i: Int): Int\l+ \>\>(i: Int): Int\l+ ascii(): Char\l+ digit_count(b: Int): Int\l+ digit_count_base_10(): Int\l+ to_c(): Char\l+ abs(): Int\l}"
+ label = "{Int||+ %(i: Int): Int\l+ \<\<(i: Int): Int\l+ \>\>(i: Int): Int\l+ code_point(): Char\l+ digit_count(b: Int): Int\l+ digit_count_base_10(): Int\l+ to_c(): Char\l+ abs(): Int\l}"
]
Discrete -> Int [dir=back arrowtail=open style=dashed];
Numeric -> Int [dir=back arrowtail=open style=dashed];
Char [
- label = "{Char||+ to_i(): Int\l+ ascii(): Int\l+ to_lower(): Char\l+ to_upper(): Char\l+ is_digit(): Bool\l+ is_lower(): Bool\l+ is_upper(): Bool\l+ is_letter(): Bool\l+ is_whitespace(): Bool\l}"
+ label = "{Char||+ to_i(): Int\l+ ascii(): Byte\l+ code_point(): Int\l+ is_ascii(): Bool\l+ to_lower(): Char\l+ to_upper(): Char\l+ is_digit(): Bool\l+ is_lower(): Bool\l+ is_upper(): Bool\l+ is_letter(): Bool\l+ is_whitespace(): Bool\l}"
]
Discrete -> Char [dir=back arrowtail=open style=dashed];
Numeric -> Float [dir=back arrowtail=open style=dashed];
Byte [
- label = "{Byte||+ %(i: Byte): Byte\l+ \<\<(i: Int): Byte\l+ \>\>(i: Int): Byte\l}"
+ label = "{Byte||+ %(i: Byte): Byte\l+ \<\<(i: Int): Byte\l+ \>\>(i: Int): Byte\l+ ascii(): Char\l}"
]
Discrete -> Byte [dir=back arrowtail=open style=dashed];
Numeric -> Byte [dir=back arrowtail=open style=dashed];
Int [
- label = "{Int||+ %(i: Int): Int\l+ \<\<(i: Int): Int\l+ \>\>(i: Int): Int\l+ ascii(): Char\l+ digit_count(b: Int): Int\l+ digit_count_base_10(): Int\l+ to_c(): Char\l+ abs(): Int\l}"
+ label = "{Int||+ %(i: Int): Int\l+ \<\<(i: Int): Int\l+ \>\>(i: Int): Int\l+ code_point(): Char\l+ digit_count(b: Int): Int\l+ digit_count_base_10(): Int\l+ to_c(): Char\l+ abs(): Int\l}"
]
Discrete -> Int [dir=back arrowtail=open style=dashed];
Numeric -> Int [dir=back arrowtail=open style=dashed];
Char [
- label = "{Char||+ to_i(): Int\l+ ascii(): Int\l+ to_lower(): Char\l+ to_upper(): Char\l+ is_digit(): Bool\l+ is_lower(): Bool\l+ is_upper(): Bool\l+ is_letter(): Bool\l+ is_whitespace(): Bool\l}"
+ label = "{Char||+ to_i(): Int\l+ ascii(): Byte\l+ code_point(): Int\l+ is_ascii(): Bool\l+ to_lower(): Char\l+ to_upper(): Char\l+ is_digit(): Bool\l+ is_lower(): Bool\l+ is_upper(): Bool\l+ is_letter(): Bool\l+ is_whitespace(): Bool\l}"
]
Discrete -> Char [dir=back arrowtail=open style=dashed];
--- /dev/null
+1
+2
+3
+4
+1
+one
+2
+two
+# Regression test for the Nit project
var a = "éè"
print(a.length)
for i in [0..a.length[ do
- print("{i} is {a.chars[i]} ({a.chars[i].ascii})")
+ print("{i} is {a.chars[i]} ({a.chars[i].code_point})")
end
import core
var s = "𐏓".as(FlatString)
-print s.items.char_at(0).ascii.to_hex
-print s.items.char_at(4).ascii.to_hex
+print s.items.char_at(0).code_point.to_hex
+print s.items.char_at(4).code_point.to_hex
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var a = [1,2,3,4]
+with i = a.iterator do while i.is_ok do
+ print i.item
+ i.next
+end
+
+var m = new HashMap[Int, String]
+m[1] = "one"
+m[2] = "two"
+with i = m.iterator do while i.is_ok do
+ print i.key
+ print i.item
+ i.next
+end
+
+with f = "README.md".to_path.open_ro do
+ print f.read_line
+end