move standalone projects into own directory

This commit is contained in:
2023-04-27 11:39:41 -06:00
parent 5d593e22b0
commit acda704057
369 changed files with 1170 additions and 5 deletions

View File

@@ -0,0 +1,8 @@
package;
import kiss.Prelude;
import kiss.List;
import HabitModel;
@:build(kiss.Kiss.build())
class Entry {}

View File

@@ -0,0 +1,27 @@
(defNew [&prop &mut :EntryType type
&prop &mut :Array<EntryLabel> labels
&prop &mut :Bool topPriority])
(method toString []
"$?(when topPriority "! ")$(case type
((Daily days lastDayDone)
(+
(.join (for day days
(case day
(1 "M")
(2 "T")
(3 "W")
(4 "Th")
(5 "F")
(6 "S")
(7 "Su")
(otherwise (throw "bad day")))) "")
" "
lastDayDone
": "))
((Monthly days lastDayDone)
"$(days.join ",") ${lastDayDone}: ")
((Interval days lastDayDone)
"$days ${lastDayDone}: ")
(otherwise ""))$(.join (for label labels
"${label.label} $(HabitModel.pointsStr label.points)") "/")")

View File

@@ -0,0 +1,12 @@
package;
import flixel.FlxG;
import flixel.text.FlxText;
import kiss_flixel.SimpleWindow;
import kiss.Prelude;
import flixel.system.FlxSound;
import flixel.util.FlxColor;
using StringTools;
@:build(kiss.Kiss.build())
class FlxPomTimer extends FlxText {}

View File

@@ -0,0 +1,48 @@
(savedVar :Bool workMode false)
(savedVar :Float timerValue 0)
(savedVar :Float workMin 25)
(savedVar :Float breakMin 5)
(savedVar :Float longBreakMin 10)
(savedVar :Int totalPoms 0)
(prop :FlxSound dingSound)
(prop &mut :Void->Void onFinishedPom)
(prop &mut :Void->Void onStartPom)
(method getText []
"$(if workMode "FOCUS ON WORK FOR " "TAKE A BREAK FOR ")$(Std.int (/ timerValue 60)):$(.lpad (Std.string (Std.int (% timerValue 60))) "0" 2)")
(method new []
(super (fHalf FlxG.width) 0 (getText) (* 2 SimpleWindow.textSize))
(set color FlxColor.ORANGE)
(set dingSound (FlxG.sound.load "assets/ding.wav")))
(method &override :Void update [:Float elapsed]
(super.update elapsed)
(-= timerValue elapsed)
(#when debug
(when (and FlxG.keys.pressed.CONTROL FlxG.keys.justPressed.P)
(set timerValue 0)))
(when (<= timerValue 0)
(when workMode
(+= totalPoms 1)
(when onFinishedPom
(onFinishedPom)))
(set workMode !workMode)
(dingSound.play)
(set timerValue
(* 60
(if workMode
{
(when onStartPom (onStartPom))
workMin
}
(if (= 0 (% totalPoms 4))
longBreakMin
breakMin)))))
(set text (getText)))
(function resetTimer []
(set workMode false)
(set timerValue 0)
(set totalPoms 0))

View File

@@ -0,0 +1,43 @@
package;
import kiss.Prelude;
import kiss.List;
import kiss.Stream;
import sys.io.File;
import datetime.DateTime;
import datetime.DateTimeInterval;
import haxe.ds.Option;
using StringTools;
enum EntryType {
Daily(daysOfWeek:Array<Int>, lastDayDone:String);
Interval(days:Int, lastDayDone:String);
// -1 represents the last day of the month, and so on
Monthly(daysOfMonth:Array<Int>, lastDayDone:String);
Bonus;
Todo;
}
typedef EntryLabel = {
label:String,
points:Int
};
typedef RewardFile = {
path: String,
startingPoints: Int,
puzzleWidth: Int,
puzzleHeight: Int,
piecesPerPoint: Int,
skipped: Bool
};
typedef Puzzle = {
path:Null<String>,
index:Int,
outOf:Int
}
@:build(kiss.Kiss.build())
class HabitModel {}

View File

@@ -0,0 +1,314 @@
(prop :Array<Entry> dailyEntries [])
(prop :Array<Entry> monthlyEntries [])
(prop :Array<Entry> intervalEntries [])
(prop :Array<Entry> bonusEntries [])
(prop :Array<Entry> todoEntries [])
(prop :kiss.List<RewardFile> rewardFiles [])
(prop &mut :Int pomodoroPoints 0)
(defNew [&prop :String textFile]
(let [s (Stream.fromFile textFile)
&mut lastHeader ""]
// TODO could be whileLet
(loop
(case (s.takeLine)
((Some "DAILY")
(set lastHeader "DAILY"))
((Some "MONTHLY")
(set lastHeader "MONTHLY"))
((Some "INTERVAL")
(set lastHeader "INTERVAL"))
((Some "BONUS")
(set lastHeader "BONUS"))
((Some "TODO")
(set lastHeader "TODO"))
((Some "FILES")
(set lastHeader "FILES"))
((Some "POMODORO")
(set lastHeader "POMODORO"))
((when (apply = (concat ["-"] (line.split ""))) (Some line))
(continue))
((Some "") (continue))
// Types won't unify with the next case, so this is its own:
((when (= lastHeader "FILES") (Some line))
(rewardFiles.push
(let [parts (line.split " ")
skipped (case (parts.pop)
("true" true)
("false" false)
(otherwise (throw "bad bool")))
piecesPerPoint (Std.parseInt (parts.pop))
puzzleHeight (Std.parseInt (parts.pop))
puzzleWidth (Std.parseInt (parts.pop))
startingPoints (Std.parseInt (parts.pop))
path (parts.join " ")]
(objectWith path startingPoints puzzleWidth puzzleHeight piecesPerPoint skipped))))
((when (= lastHeader "POMODORO") (Some line)) (set pomodoroPoints (Std.parseInt line)))
((Some line)
(let [topPriority (line.startsWith "! ")]
(when topPriority (set line (line.substr 2)))
(.push
(case lastHeader
("DAILY" dailyEntries)
("MONTHLY" monthlyEntries)
("INTERVAL" intervalEntries)
("BONUS" bonusEntries)
("TODO" todoEntries)
(otherwise (throw "bad header")))
(new Entry
(case lastHeader
("BONUS" Bonus)
("TODO" Todo)
("DAILY"
(case (line.split ":")
([noColon]
(Daily
// all days of week
(collect (range 1 8))
// never done before
""))
([::&mut preColon ...afterColon]
(set line (afterColon.join ":"))
(Daily
// Days of week specified by abbreviation:
(sort (filter
[
// disambiguate Th from T and Su from S:
(when (contains preColon "Th") {(set preColon (StringTools.replace preColon "Th" "")) 4})
(when (contains preColon "Su") {(set preColon (StringTools.replace preColon "Su" "")) 7})
(when (contains preColon "M") 1)
(when (contains preColon "T") 2)
(when (contains preColon "W") 3)
(when (contains preColon "F") 5)
(when (contains preColon "S") 6)
]))
// Last date completed after that:
(ifLet [[days date] (preColon.split " ")]
date
"")))
(otherwise (throw "bad line"))))
("MONTHLY"
(case (line.split ": ")
([::&mut preColon ...afterColon]
(set line (afterColon.join ": "))
(Monthly
// Days of month can be positive (1-31) or negative (-1 to -31)
(map (.split (first (preColon.split " ")) ",") Std.parseInt)
// Last date completed after that:
(ifLet [[::days ...date] (preColon.split " ")]
(date.join " ")
"")))
(otherwise (throw "bad line"))))
("INTERVAL"
(case (line.split ": ")
([::&mut preColon ...afterColon]
(set line (afterColon.join ": "))
(case (preColon.split " ")
([days]
(Interval (Std.parseInt days) ""))
([::days ...lastDayDone]
(Interval (Std.parseInt days) (lastDayDone.join " ")))
(otherwise (throw "bad interval habit: $line"))))
(otherwise (throw "bad interval habit: $line"))))
(otherwise (throw "bad header: $lastHeader")))
(for l (line.split "/")
(object
label (StringTools.trim (withoutPointsStr l))
points (countPoints l)))
topPriority))))
(otherwise (break))))))
(method :Array<Entry> allEntries []
(cast (concat
dailyEntries
monthlyEntries
intervalEntries
bonusEntries
todoEntries)))
(method :Array<Entry> allUndeletedEntries []
(filter (allEntries) isNotDeleted))
(method :Int totalPoints []
(+ pomodoroPoints (apply + (for l (flatten (for e (allEntries) e.labels)) l.points))))
(function stringify [:Entry e]
(e.toString))
(function :String stringifyRewardFile [:RewardFile rewardFile]
"${rewardFile.path} ${rewardFile.startingPoints} ${rewardFile.puzzleWidth} ${rewardFile.puzzleHeight} ${rewardFile.piecesPerPoint} ${rewardFile.skipped}")
(method :Void save []
(localVar &mut content "DAILY\n-----\n")
(+= content (.join (map dailyEntries stringify) "\n") "\n")
(+= content "\nMONTHLY\n--------\n")
(+= content (.join (map monthlyEntries stringify) "\n") "\n")
(+= content "\nINTERVAL\n--------\n")
(+= content (.join (map intervalEntries stringify) "\n") "\n")
(+= content "\nBONUS\n-----\n")
(+= content (.join (map bonusEntries stringify) "\n") "\n")
(+= content "\nTODO\n----\n")
(+= content (.join (map todoEntries stringify) "\n") "\n")
(+= content "\nPOMODORO\n--------\n${pomodoroPoints}\n")
(+= content "\nFILES\n-----\n")
(+= content (.join (map rewardFiles stringifyRewardFile) "\n") "\n")
(File.saveContent textFile
content))
// With rotating entries, the active one is the first one with the lowest score:
(function :EntryLabel activeLabel [:Entry e]
(let [lowScore (apply min (for label e.labels label.points))]
(doFor label e.labels (when (= lowScore label.points) (return label)))
(throw "no active?!")))
(function todayString []
(let [d (Date.now)] "$(d.getDate)-$(+ 1 (d.getMonth))-$(d.getFullYear)"))
(function isDeleted [:Entry e]
(or (.startsWith .label (first e.labels) "~")
(case e.type
(Todo !(= 0 .points (activeLabel e)))
(otherwise false))))
(function isNotDeleted [:Entry e]
!(isDeleted e))
(function _isActive [:Entry e]
(when (isDeleted e)
(return false))
(case e.type
((Daily days lastDayDone)
(let [&mut today (.getDay (Date.now))]
(when (= today 0) (set today 7))
(and !(= lastDayDone (todayString)) (contains days today))))
((Monthly days lastDayDone)
// TODO logic
(let [&mut nextDay
(DateTime.fromDate (Date.now))
oneDayInterval (DateTimeInterval.create (DateTime.make 1970 1 1) (DateTime.make 1970 1 2))
dayToEndSearch
(if lastDayDone
(DateTime.fromString lastDayDone)
(let [&mut now (DateTime.fromDate (Date.now))]
(until (= 1 (now.getDay)) #{now -= oneDayInterval;}#)
now))]
(until (and (= (nextDay.getDay) (dayToEndSearch.getDay)) (= (nextDay.getMonth) (dayToEndSearch.getMonth)) (= (nextDay.getYear) (dayToEndSearch.getYear)))
(let [daysInMonth (DateTime.daysInMonth (nextDay.getMonth) (nextDay.isLeapYear))
adjustedDays (for day days (% (+ daysInMonth day) daysInMonth))]
(when (contains adjustedDays (nextDay.getDay)) (return true)))
#{nextDay -= oneDayInterval;}#)
(return false)))
((Interval days lastDayDone)
(or !lastDayDone (<= days #{(DateTime.fromDate(Date.now()) - DateTime.fromString(lastDayDone)).getTotalDays();}#)))
(Todo (= 0 .points (activeLabel e)))
(otherwise true)))
// Check if an entry is active PRE-top priority filtering
(method :Array<Entry> _activeDailyEntries []
(filter dailyEntries _isActive))
(method :Array<Entry> _activeMonthlyEntries []
(filter monthlyEntries _isActive))
(method :Array<Entry> _activeIntervalEntries []
(filter intervalEntries _isActive))
(method :Array<Entry> _activeBonusEntries []
(filter bonusEntries _isActive))
(method :Array<Entry> _activeTodoEntries []
(filter todoEntries _isActive))
(method :Array<Entry> _allActiveEntries []
(cast (concat
(_activeDailyEntries)
(_activeMonthlyEntries)
(_activeIntervalEntries)
(_activeBonusEntries)
(_activeTodoEntries))))
(prop &mut :Bool showLowerPriority false)
(method :Bool topPriorityIsActive []
?(unless showLowerPriority (apply or (for e (_allActiveEntries) e.topPriority))))
(defMacro topPriority [name]
`(method :Array<Entry> ,name []
(let [_active (,(ReaderExp.Symbol (+ "_" (symbolNameValue name))))]
(if (topPriorityIsActive)
(filter _active ->e e.topPriority)
_active))))
(topPriority activeDailyEntries)
(topPriority activeMonthlyEntries)
(topPriority activeIntervalEntries)
(topPriority activeBonusEntries)
(topPriority activeTodoEntries)
(method addEntry [:EntryType type :Array<String> labels :Bool topPriority]
(.push (case type
(Todo todoEntries)
(Bonus bonusEntries)
((Interval _ _) intervalEntries)
((Daily _ _) dailyEntries)
((Monthly _ _) monthlyEntries)
(otherwise (throw "")))
(new Entry type (for label labels (objectWith [points 0] label)) topPriority))
(save))
(method deleteEntry [:Entry e]
(set e.labels (for label e.labels (object points label.points label "~")))
(save))
(method toggleEntryPriority [:Entry e]
(set e.topPriority !e.topPriority)
(save))
(method addRewardFile [path startingPoints puzzleWidth puzzleHeight piecesPerPoint]
(rewardFiles.push (objectWith [skipped false] path startingPoints puzzleWidth puzzleHeight piecesPerPoint))
(save))
(method skipRewardFile []
(set .skipped (last rewardFiles) true)
(save))
(method addPoint [:Entry e]
(let [label (activeLabel e)]
(+= label.points 1)
// For task-list types, set lastDayDone when the final label is done
(when (apply = (for label e.labels label.points))
(whenLet [(Daily days lastDayDone) e.type]
(set e.type (Daily days (HabitModel.todayString))))
(whenLet [(Monthly days lastDayDone) e.type]
(set e.type (Monthly days (.toString (DateTime.now)))))
(whenLet [(Interval days lastDayDone) e.type]
(set e.type (Interval days (.toString (DateTime.now)))))))
(save))
(method addPomPoint []
(+= pomodoroPoints 1)
(save))
(var tallyUnit 5)
(function pointsStr [points]
(let [&mut str "" symbols ["+" "*" "\$"]]
(doFor i (reverse (collect (range symbols.length)))
(let [scaledTallyUnit (^ tallyUnit i)
tallies (Math.floor (/ points scaledTallyUnit))]
(+= str (* (nth symbols i) tallies))
(-= points (* tallies scaledTallyUnit))))
str))
(function withoutPointsStr [:String label]
(doFor c (.split "|+*\$" "") (set label (label.replace c "")))
label)
(function countPoints [:String pointStr]
(apply + (for char (pointStr.split "")
(case char
("|" 1)
("+" 1)
("*" tallyUnit)
("\$" (^ tallyUnit 2))
(otherwise 0)))))

View File

@@ -0,0 +1,68 @@
package;
using StringTools;
import haxe.Constraints;
import flash.display.BitmapData;
import haxe.io.Path;
import flixel.FlxG;
import flixel.FlxState;
import flixel.group.FlxGroup;
import flixel.FlxSprite;
import flixel.FlxCamera;
import flixel.util.FlxColor;
import flixel.text.FlxText;
import flixel.math.FlxRandom;
import flixel.math.FlxPoint;
import flixel.math.FlxRect;
import openfl.geom.Rectangle;
import openfl.geom.Point;
import openfl.geom.ColorTransform;
import flixel.util.FlxSpriteUtil;
using flixel.util.FlxSpriteUtil;
import flixel.util.FlxSave;
import flixel.input.mouse.FlxMouseEventManager;
import flixel.addons.display.FlxExtendedSprite;
import flixel.addons.plugin.FlxMouseControl;
import kiss_flixel.KissInputText;
import kiss.Prelude;
import kiss.List;
import kiss_tools.FlxKeyShortcutHandler;
import HabitModel;
import sys.FileSystem;
import hx.strings.Strings;
import datetime.DateTime;
import flixel.ui.FlxButton;
import flixel.ui.FlxBar;
import flixel.addons.util.FlxAsyncLoop;
using kiss_flixel.CameraTools;
using kiss_flixel.GroupTools;
using kiss_flixel.DebugLayer;
import kiss_flixel.KissExtendedSprite;
import kiss_flixel.SimpleWindow;
import haxe.ds.Option;
import jigsawx.JigsawPiece;
import jigsawx.Jigsawx;
import jigsawx.math.Vec2;
import kiss_flixel.DragToSelectPlugin;
import re_flex.R;
import FlxPomTimer;
typedef StartPuzzleFunc = (Int, Int) -> Void;
@:build(kiss.Kiss.build())
class HabitState extends FlxState {
public function drawPieceShape( surface: FlxSprite, jig: JigsawPiece, scale:Float, fillColor: FlxColor, ?outlineColor: FlxColor)
{
if (outlineColor == null) outlineColor = fillColor;
var points = [for (point in jig.getPoints()) new FlxPoint(point.x / scale + ROT_PADDING, point.y / scale + ROT_PADDING)];
points.push(points[0]);
FlxSpriteUtil.drawPolygon(
surface,
points,
fillColor,
{
thickness: 1,
color: outlineColor
});
}
}

View File

@@ -0,0 +1,998 @@
(loadFrom "kiss-tools" "src/kiss_tools/RefactorUtil.kiss")
(prop &mut :Jigsawx jigsaw)
(prop &mut :FlxCamera pieceCamera)
(prop &mut :FlxCamera uiCamera)
(defAlias &ident textSize SimpleWindow.textSize)
(prop &mut :FlxPomTimer pomTimer null)
(prop &mut :FlxText availableMatchesText (new FlxText 0 0 0 "" SimpleWindow.textSize))
(method &override :Void create []
(set FlxG.sound.soundTrayEnabled false)
(set FlxG.autoPause false)
(add logTexts)
(set Prelude.printStr log)
(defAndCall method newPieceCamera
(if pieceCamera
{
(FlxG.cameras.remove pieceCamera true)
(set pieceCamera (new FlxCamera))
(FlxG.cameras.add pieceCamera)
}
(set pieceCamera FlxG.camera))
(set FlxG.camera pieceCamera)
(when debugLayer
(set debugLayer.cameras [pieceCamera]))
(when uiCamera
(FlxG.cameras.remove uiCamera false)
(FlxG.cameras.add uiCamera)))
(set uiCamera (new FlxCamera))
(set SimpleWindow.defaultCamera uiCamera)
(set uiCamera.bgColor FlxColor.TRANSPARENT)
(set availableMatchesText.color FlxColor.LIME)
(set availableMatchesText.cameras [uiCamera])
(add availableMatchesText)
(FlxG.cameras.add uiCamera)
(FlxG.plugins.add (new FlxMouseControl))
(set FlxMouseControl.sortIndex "priorityID")
(set bgColor FlxColor.TRANSPARENT)
(set pomTimer (new FlxPomTimer))
(set pomTimer.cameras [uiCamera])
(super.create))
(defAlias &ident KEYBOARD_SCROLL_SPEED (keyboardScrollSpeed))
(method keyboardScrollSpeed []
(fHalf (max rewardSprite.pixels.width rewardSprite.pixels.height)))
(prop &mut :EntryType typeAdding Todo)
(prop &mut :Array<String> labelsAdding [])
(prop &mut :Bool addingLabels false)
(prop &mut :KissInputText entryNameText)
(prop &mut :DebugLayer debugLayer null)
(prop &mut t 1)
(prop :FlxRect disableMouse (new FlxRect 0 0 0 0))
(method &override :Void update [:Float elapsed]
(prop :Array<Function> nextFrameFunctions [])
(method nextFrame [:Function f]
(nextFrameFunctions.push f))
(when nextFrameFunctions
(whileLet [f (nextFrameFunctions.shift)]
(f)))
(set availableMatchesText.text "$(countAvailableMatches) matches can be made.")
(set availableMatchesText.y (- FlxG.height availableMatchesText.height))
(set availableMatchesText.x (- FlxG.width availableMatchesText.width))
// workaround for text box somehow losing focus:
(when entryNameText (set entryNameText.hasFocus true))
(super.update elapsed)
(when (and pomWasRunning !pomResumeWindow !pomStartCheck)
(entryWindow.hide)
(set pomStartCheck true)
(set pomResumeWindow
(SimpleWindow.promptForChoice "A pomodoro timer was interrupted. Resume it now?"
[
"Yes"
"No"
]
->:Void [:String choice]
(case choice
("Yes" (startPomodoros)(backToEntryWindow))
("No"
(set pomWasRunning false)
(backToEntryWindow))
(never otherwise))
null null FlxColor.LIME 0.9 0.9 true xKey null null ->[] {(set pomWasRunning false)(backToEntryWindow)})))
(if (windowIsShown)
{
(set FlxMouseControl.mouseZone disableMouse)
(when FlxMouseControl.dragTarget
(FlxMouseControl.dragTarget.stopDrag)
(set FlxMouseControl.dragTarget null))
}
(set FlxMouseControl.mouseZone null))
(#when debug
(debugLayer.clear)
(when (and model.rewardFiles rewardSprites.alive FlxG.debugger.visible)
(doFor s rewardSprites
(let [i (dictGet indexMap s)
jig (dictGet pieceData i)]
(kiss_flixel.SpriteTools.writeOnSprite "$i" 32 s (object x (Percent 0.5) y (Percent 0.5)) FlxColor.RED)
(kiss_flixel.SpriteTools.writeOnSprite "(${jig.col},${jig.row})" 32 s (object x (Percent 0.5) y (Percent 0.7)) FlxColor.RED))
(let [matchZones [(matchZoneLeft s) (matchZoneRight s)(matchZoneUp s)(matchZoneDown s)]]
(doFor z matchZones
(unless z.isEmpty
(debugLayer.drawFlxRect z FlxColor.RED)))))))
(when model.rewardFiles
(unless (or bar (windowIsShown))
(let [zoom pieceCamera.zoom
scroll (pieceCamera.scroll.copyTo)]
(pieceCamera.updateScrollWheelZoom elapsed 5)
(pieceCamera.updateMouseBorderControl elapsed KEYBOARD_SCROLL_SPEED 0.002 uiCamera)
(when (or !(= zoom pieceCamera.zoom) !(scroll.equals pieceCamera.scroll))
(set save.data.zoom pieceCamera.zoom)
(set save.data.scroll pieceCamera.scroll)
(save.flush))))
(when (and entryWindow !(tempWindowIsShown))
(when FlxG.keys.justPressed.ESCAPE
(if (entryWindow.isShown)
(entryWindow.hide)
(entryWindow.show))))
(#when debug
(when FlxG.keys.justPressed.SEMICOLON
(set pieceCamera.zoom 1))
**(when FlxG.keys.justPressed.CONTROL
(set save.data.storedPositions (new Map<Int,FlxPoint>))
(set save.data.storedAngles (new Map<Int,Float>))
(set save.data.storedOrigins (new Map<Int,FlxPoint>))
(save.flush))))
(unless (and entryNameText entryNameText.alive)
(when FlxG.keys.justPressed.DELETE
(Sys.exit 0)))
// TODO provide a saner/configurable set of bindings to trigger these ui action functions
{
(unless (windowIsShown)
(when (or FlxG.mouse.justPressedRight FlxG.keys.justPressed.R)
(when draggingSprite
(draggingSprite.rotate 90)
(doFor s (recursivelyConnectedPieces draggingSprite)
(dictSet (the Map<Int,Float> save.data.storedAngles) (dictGet indexMap s) s.angle)
(dictSet (the Map<Int,FlxPoint> save.data.storedOrigins) (dictGet indexMap s) s.origin))
(save.flush))))
(method :Void startAdding [:EntryType type]
(set typeAdding type)
(set labelsAdding [])
(set addingLabels true)
(localVar typeDescriptor
(case type
(Bonus "bonus habit")
(Todo "task")
((Daily _ _) "daily task")
((Monthly _ _) "monthly task")
((Interval _ _) "interval task")
(null (throw "type should never be null"))))
(localVar multipleLabelDescriptor
(case type
(Bonus "cycle of alternating habits")
(otherwise "series of steps for completing this task")))
(localVar title
"Add a label for this ${typeDescriptor}, or use SHIFT+ENTER to add a ${multipleLabelDescriptor}:")
(set entryCreationWindow (new SimpleWindow title null null 0.9 0.9 true xKey leftKey rightKey backToEntryWindow))
(set entryNameText (defAndCall method newNameInputText
(let [t (new KissInputText 0 0 FlxG.width "" textSize true)]
(set t.customFilterPattern (new EReg (R.oneOfChars #"/+$*[]{}"# ) ""))
t)))
(entryCreationWindow.addControl entryNameText)
(entryCreationWindow.makeText "Create" FlxColor.LIME ->:Void _ (addCreatedEntry))
(when entryWindow
(set entryWindow.keyboardEnabled false))
(entryCreationWindow.show)
(set entryNameText.hasFocus true))
(when (and entryNameText FlxG.keys.justPressed.ENTER)
(cond
((and FlxG.keys.pressed.SHIFT addingLabels)
(when (entryNameText.text.trim)
(entryCreationWindow.makeText entryNameText.text)
(labelsAdding.push entryNameText.text)
(set entryNameText.text "")
(set entryNameText.caretIndex 0)))
(addingLabels
(addCreatedEntry))
(true
(startAddingInterval))))
}
// Left and right arrow keys can switch between unlocked puzzles
(unless (or entryNameText (tempWindowIsShown))
(when FlxG.keys.justPressed.LEFT
(defAndCall method clearBar
(when bar
(remove bar)
(remove asyncLoop)))
(unless (= rewardFileIndex minRewardFile)
--rewardFileIndex
(while .skipped (nth model.rewardFiles rewardFileIndex)
--rewardFileIndex)
(refreshModel)))
(when FlxG.keys.justPressed.RIGHT
(clearBar)
(unless (= rewardFileIndex maxRewardFile)
++rewardFileIndex
(while .skipped (nth model.rewardFiles rewardFileIndex)
++rewardFileIndex)
(refreshModel)))))
(prop &mut :FlxSave save null)
(prop &mut :SimpleWindow entryWindow null)
(prop &mut :SimpleWindow puzzlePackChoiceWindow null)
(prop &mut :SimpleWindow entryDeletionWindow null)
(prop &mut :SimpleWindow entryEditWindow null)
(prop &mut :SimpleWindow entryCreationWindow null)
(prop &mut :SimpleWindow priorityWindow null)
(prop &mut :SimpleWindow pomResumeWindow null)
(method windowIsShown []
(or (tempWindowIsShown) (and entryWindow (entryWindow.isShown))))
(method tempWindowIsShown []
(doFor window [puzzlePackChoiceWindow entryDeletionWindow entryCreationWindow priorityWindow entryEditWindow pomResumeWindow]
(when (and window (window.isShown))
(return true)))
false)
(prop &mut :FlxTypedGroup<FlxText> logTexts (new FlxTypedGroup))
(prop &mut :HabitModel model null)
(method smallerDimension [] (min rewardSprite.pixels.width rewardSprite.pixels.height))
// TODO these variables don't do exactly what I think they do when scaled, like at all:
(defAlias &ident EDGE_LEEWAY 25)
(defAlias &ident BUBBLE_SIZE 15)
(defAlias &ident PUZZLE_WIDTH .puzzleWidth (nth model.rewardFiles rewardFileIndex))
(defAlias &ident PUZZLE_HEIGHT .puzzleHeight (nth model.rewardFiles rewardFileIndex))
(method roughOptimalScale []
(* (/ (max PUZZLE_WIDTH PUZZLE_HEIGHT) MIN_PUZZLE_SIZE) (/ 367 (smallerDimension))))
(defAlias &ident TOTAL_PIECES (* PUZZLE_WIDTH PUZZLE_HEIGHT))
(prop &mut :FlxSprite rewardSprite null)
(prop &mut :FlxTypedGroup<KissExtendedSprite> rewardSprites null)
(prop &mut :Map<Int,KissExtendedSprite> matchingPiecesLeft (new Map))
(prop &mut :Map<Int,KissExtendedSprite> matchingPiecesRight (new Map))
(prop &mut :Map<Int,KissExtendedSprite> matchingPiecesUp (new Map))
(prop &mut :Map<Int,KissExtendedSprite> matchingPiecesDown (new Map))
(prop &mut :Map<Int,JigsawPiece> pieceData (new Map))
(prop &mut :Map<Int,Array<KissExtendedSprite>> connectedPieces (new Map))
(prop &mut :Map<KissExtendedSprite,Int> indexMap (new Map))
(prop &mut :Map<Int,KissExtendedSprite> spriteMap (new Map)) // Because rewardSprites will be re-ordered in depth handling, this is required
(prop &mut lastRewardFileIndex -1)
(prop &mut rewardFileIndex 0)
(prop &mut :Null<Int> minRewardFile null)
(prop &mut :Null<Int> maxRewardFile null)
(defAlias &ident SCROLL_BOUND_MARGIN (scrollBoundMargin))
(method scrollBoundMargin []
(max rewardSprite.pixels.width rewardSprite.pixels.height))
(prop &mut :KissExtendedSprite draggingSprite null)
(prop &mut :FlxPoint draggingLastPos null)
// Main.hx sets off 99% of the app's logic by parsing the model file and calling setModel on startup and on a 30s loop:
(method backToEntryWindow []
(when priorityWindow (set priorityWindow.cameraColumn 0))
(set entryNameText null)
(nextFrame ->(entryWindow.show)))
(method :Void setModel [m &opt :RewardFile currentRewardFile]
(set model m)
(set pomTimer.onFinishedPom ->:Void {(model.addPomPoint) (refreshModel) (entryWindow.hide)})
(set pomTimer.onStartPom ->:Void (entryWindow.show))
(let [p (m.totalPoints)
&mut i 0
&mut puzzleUnlocked -1]
// Find, load, and add the current reward image as big as possible:
(unless currentRewardFile
(set currentRewardFile (nth m.rewardFiles 0))
(cond
((and m.rewardFiles !.skipped (last m.rewardFiles))
(while (> p .startingPoints (nth m.rewardFiles i))
(set rewardFileIndex i)
(set currentRewardFile (nth m.rewardFiles i))
(unless minRewardFile
(unless .skipped (nth m.rewardFiles i)
(set minRewardFile i)))
(unless .skipped (nth m.rewardFiles i)
(set maxRewardFile i))
(when (>= ++i m.rewardFiles.length)
--i
(let [lastStartingPoints .startingPoints (nth m.rewardFiles i)
piecesPerPoint .piecesPerPoint (nth m.rewardFiles i)
nextStartingPoints (+ lastStartingPoints (Math.ceil (/ TOTAL_PIECES piecesPerPoint)))]
(when (> p nextStartingPoints)
(set puzzleUnlocked nextStartingPoints))
(break)))))
((and m.rewardFiles .skipped (last m.rewardFiles))
(set puzzleUnlocked (max 0 (- p 1))))
(true
(set puzzleUnlocked 0))))
(when m.rewardFiles
(makeRewardSprites m p currentRewardFile))
(localVar &mut windowWasShown true)
(localVar &mut :Null<Int> cameraColumn null)
(when entryWindow
(set cameraColumn entryWindow.cameraColumn)
(set windowWasShown (entryWindow.isShown))
(entryWindow.hide))
(set entryWindow (new SimpleWindow "" (FlxColor.fromRGBFloat 0 0 0 0.5) FlxColor.WHITE 0.9 0.9))
(set entryWindow.cameras [uiCamera])
(set entryWindow.textColor FlxColor.LIME)
(when m.rewardFiles
(_makeText "Puzzle #$(+ 1 rewardFileIndex) / ${model.rewardFiles.length}" (max 0 (- TOTAL_PIECES (* currentRewardFile.piecesPerPoint (- p currentRewardFile.startingPoints)))))
(set entryWindow.textColor (FlxColor.fromRGBFloat 0.2 0.2 0.2))
(_makeText "{space} Cycle background color" 0
->_
(defAndCall method toggleBackgroundColor
(set save.data.backgroundIndex #{(save.data.backgroundIndex + 1) % backgroundOptions.length;}#)
(save.flush)
(refreshModel)))
(set entryWindow.textColor (FlxColor.LIME.getDarkened))
(_makeText "Create a habit or task" 0
->_
(defAndCall method createHabitOrTask
(entryWindow.hide)
(set entryCreationWindow (SimpleWindow.promptForChoice "Create which type of habit/task?"
[
"Daily: every day, or on specific days of the week"
"Monthly: on specific days of the month, or specific # of days before the end of the month"
"Interval: needs to be done again after specific # of days"
"Task: only needs to be done once"
"Bonus: can be done to earn points at any time, any number of times"
]
->:Void [:String choice]
(case (.takeUntilAndDrop (kiss.Stream.fromString choice) ":")
((Some "Daily") (createDailyEntry))
((Some "Monthly") (createMonthlyEntry))
((Some "Interval") (createIntervalEntry))
((Some "Task") (createTaskEntry))
((Some "Bonus") (createBonusEntry))
(otherwise (throw "nonexistent choice")))
null null FlxColor.LIME 0.9 0.9 true xKey leftKey rightKey backToEntryWindow))))
(_makeText "Choose Top-Priority habits and tasks" 0
->_
(defAndCall method choosePriorities
(entryWindow.hide)
(let [cameraColumn (when priorityWindow priorityWindow.cameraColumn)
pw (SimpleWindow.promptForChoice "Choose your top priorities. A ! will appear in front of them"
(model.allUndeletedEntries)
->:Void [:Entry e] {
(model.toggleEntryPriority e)
(model.save)
(refreshModel)
(priorityWindow.clearActions)
(priorityWindow.show)
(nextFrame ->{
(priorityWindow.hide)
(choosePriorities)
})
}
null null FlxColor.WHITE 0.9 0.9 true (defAndReturn prop xKey "escape") (defAndReturn prop leftKey "left") (defAndReturn prop rightKey "right") backToEntryWindow true)]
(pw.show cameraColumn)
(set priorityWindow pw))))
(_makeText "Edit a habit or task's labels" 0
->_
(defAndCall method chooseEditLabels
(entryWindow.hide)
(let [editWindow (SimpleWindow.promptForChoice "Edit which habit/task's labels?"
(model.allUndeletedEntries)
editLabels
null null FlxColor.WHITE 0.9 0.9 true xKey leftKey rightKey backToEntryWindow true)]
(set entryEditWindow editWindow))))
(let [showOrHide (if model.showLowerPriority "Hide" "Show")]
(_makeText "$showOrHide lower-priority habits and tasks" 0
->_
(defAndCall method toggleLowerPriority
(set model.showLowerPriority !model.showLowerPriority)
(refreshModel))))
(prop &mut pomRunning false)
(prop &mut pomStartCheck false)
(savedVar :Bool pomWasRunning false)
(if pomRunning
(_makeText "Stop Pomodoro Timer Mode" m.pomodoroPoints
->_ (defAndCall method stopPomodoros
(set pomRunning false)
(set pomWasRunning false)
(remove pomTimer)
(refreshModel)))
(_makeText "Start Pomodoro Timer Mode" m.pomodoroPoints
->_
(defAndCall method startPomodoros
(set pomRunning true)
(set pomWasRunning true)
(if FlxPomTimer.workMode
(entryWindow.show)
(entryWindow.hide))
(add pomTimer)
(refreshModel))))
(set entryWindow.textColor (FlxColor.RED.getDarkened))
(_makeText "Reset Pomodoro Timer" 0
->_ {
(stopPomodoros)
(FlxPomTimer.resetTimer)
})
(_makeText "Delete a habit or task" 0
->_
(defAndCall method deleteHabitOrTask
(entryWindow.hide)
(let [delWindow (SimpleWindow.promptForChoice "Delete which habit/task? (You will keep all your points)"
(model.allUndeletedEntries)
->:Void [:Entry e] {
(model.deleteEntry e)
(model.save)
(refreshModel)
(entryWindow.show)
}
null null FlxColor.WHITE 0.9 0.9 true xKey leftKey rightKey backToEntryWindow true)]
(set entryDeletionWindow delWindow))))
(when (= rewardFileIndex (- m.rewardFiles.length 1))
(_makeText "Abandon this puzzle" 0
->_
(defAndCall method skipPuzzle
(entryWindow.hide)
(model.skipRewardFile)
(setModel model)))))
(set entryWindow.textColor FlxColor.ORANGE)
(map (m.activeDailyEntries) makeText)
(set entryWindow.textColor FlxColor.GREEN)
(map (m.activeMonthlyEntries) makeText)
(set entryWindow.textColor FlxColor.CYAN)
(map (m.activeIntervalEntries) makeText)
(set entryWindow.textColor FlxColor.WHITE)
(map (m.activeBonusEntries) makeText)
(set entryWindow.textColor FlxColor.YELLOW)
(map (m.activeTodoEntries) makeText)
(when windowWasShown
(entryWindow.show cameraColumn))
(when !(= puzzleUnlocked -1)
(startPuzzlePackChoice puzzleUnlocked)))
(when debugLayer
(remove debugLayer))
(unless debugLayer
(set debugLayer (new DebugLayer))
(set debugLayer.cameras [pieceCamera]))
(add debugLayer))
(method refreshModel [&opt m]
(let [m (or m model)]
(setModel m (nth m.rewardFiles rewardFileIndex))))
(prop &mut textY 0)
(prop :Array<FlxColor> backgroundOptions [
FlxColor.BLACK
FlxColor.WHITE
FlxColor.GRAY
])
(function nameForSave [:String name]
(doFor forbiddenChar (.split #"~%&\;:"',<>?# "# "")
(set name (name.replace forbiddenChar "")))
name)
(method makeRewardSprites [m p currentRewardFile]
(set save (new FlxSave))
(assert (save.bind (nameForSave currentRewardFile.path)) "failed to bind save data")
(unless save.data.storedPositions
(set save.data.storedPositions (new Map<Int,FlxPoint>)))
(unless save.data.storedAngles
(set save.data.storedAngles (new Map<Int,Float>)))
(unless save.data.storedOrigins
(set save.data.storedOrigins (new Map<Int,FlxPoint>)))
(unless save.data.backgroundIndex
(set save.data.backgroundIndex 0))
(unless (and (= lastRewardFileIndex rewardFileIndex) (= lastTotalPoints (m.totalPoints)))
// When the current puzzle has changed:
(unless (= lastRewardFileIndex rewardFileIndex)
// Make a new camera so scroll from the last puzzle doesn't start the camera out of boundS
(newPieceCamera)
(set pieceCamera.bgColor (nth backgroundOptions save.data.backgroundIndex))
(set rewardSprite
(new FlxSprite 0 0
(BitmapData.fromFile
currentRewardFile.path)))
(set matchingPiecesLeft (new Map))
(set matchingPiecesRight (new Map))
(set matchingPiecesUp (new Map))
(set matchingPiecesDown (new Map))
(set pieceData (new Map))
(set connectedPieces (new Map))
(doFor i (range TOTAL_PIECES) (dictSet connectedPieces i []))
(set indexMap (new Map))
(set spriteMap (new Map))
(rewardSprite.setGraphicSize FlxG.width 0)
(rewardSprite.updateHitbox)
(when (> rewardSprite.height FlxG.height)
(rewardSprite.setGraphicSize 0 FlxG.height))
(rewardSprite.updateHitbox)
(rewardSprite.screenCenter)
(unless save.data.zoom
(set pieceCamera.zoom rewardSprite.scale.x))
// TODO the rewardSprite can be the "box image" for player reference
(rewardSprite.scale.set 1 1)
(when rewardSprites
#{
var plugin = FlxG.plugins.get(DragToSelectPlugin);
plugin.clearEnabledSprites();
}#
(rewardSprites.destroy)
(remove rewardSprites)
(set rewardSprites null)))
(unless rewardSprites
(set rewardSprites (new FlxTypedGroup))
// add rewardSprites group before enabling drag-to-select on instances, but kill it so pieces aren't rendered until they are all loaded
(add rewardSprites)
(rewardSprites.kill))
(let [r (new FlxRandom (Strings.hashCode currentRewardFile.path))
ros (roughOptimalScale)
graphicWidth (* ros rewardSprite.pixels.width)
graphicHeight (* ros rewardSprite.pixels.height)
pieceAssetWidth (/ (- graphicWidth (* EDGE_LEEWAY 2)) PUZZLE_WIDTH)
pieceAssetHeight (/ (- graphicHeight (* EDGE_LEEWAY 2)) PUZZLE_HEIGHT)
j (new Jigsawx pieceAssetWidth pieceAssetHeight graphicWidth graphicHeight EDGE_LEEWAY BUBBLE_SIZE PUZZLE_HEIGHT PUZZLE_WIDTH r)
PIECE_WIDTH
(/ rewardSprite.width PUZZLE_WIDTH)
PIECE_HEIGHT
(/ rewardSprite.height PUZZLE_HEIGHT)
:Array<FlxPoint> startingPoints []
:Array<Float> startingAngles []]
(let [&mut i 0]
(doFor y (range PUZZLE_HEIGHT)
(doFor x (range PUZZLE_WIDTH)
(startingAngles.push (* 90 (r.int 0 3)))
(startingPoints.push
(new FlxPoint (+ rewardSprite.x (* x PIECE_WIDTH)) (+ rewardSprite.y (* y PIECE_HEIGHT))))
(+= i 1))))
(r.shuffle startingPoints)
(set jigsaw j)
(r.shuffle jigsaw.jigs)
(localVar piecesUnlocked (min TOTAL_PIECES (* currentRewardFile.piecesPerPoint (- p currentRewardFile.startingPoints))))
(localVar piecesAlreadyMade rewardSprites.length)
(localVar newPieces (- piecesUnlocked piecesAlreadyMade))
(prop &mut :Array<Array<KissExtendedSprite>> spriteGrid)
(prop &mut :Array<Array<Int>> indexGrid)
(unless (< 0 piecesAlreadyMade)
(set spriteGrid (for y (range PUZZLE_HEIGHT) (for x (range PUZZLE_WIDTH) null)))
(set indexGrid (for y (range PUZZLE_HEIGHT) (for x (range PUZZLE_WIDTH) -1))))
(localVar makeJig -+>count []
(let [i (+ piecesAlreadyMade count -1)
jig (nth jigsaw.jigs i)
pos (ifLet [point (dictGet (the Map<Int,FlxPoint> save.data.storedPositions) i)]
point
(.addPoint (nth startingPoints i) camera.scroll))
angle (ifLet [angle (dictGet (the Map<Int,Float> save.data.storedAngles) i)]
angle
(nth startingAngles i))
&mut s (dictGet spriteMap i)
source (new FlxSprite)
mask (new FlxSprite)
sourceRect (new Rectangle (/ jig.xy.x ros) (/ jig.xy.y ros) (/ jig.wh.x ros) (/ jig.wh.y ros))]
(unless s
(set s (new KissExtendedSprite pos.x pos.y))
(set s.angle angle)
(set s.priorityID i)
(dictSet (the Map<Int,FlxPoint> save.data.storedPositions) i pos)
(setNth spriteGrid jig.row jig.col s)
(setNth indexGrid jig.row jig.col i)
(dictSet pieceData i jig)
(dictSet indexMap s i)
(dictSet spriteMap i s)
(set s.draggable true)
(s.enableMouseDrag false true)
(set s.mouseStartDragCallback
->:Void [s x y]
(let [s (cast s KissExtendedSprite)]
(set s.priorityID (+ 1 .priorityID (last (the kiss.List<KissExtendedSprite> rewardSprites.members))))
(let [connectedPieces (recursivelyConnectedPieces s)]
// Bring currently held pieces to the front:
(rewardSprites.bringAllToFront connectedPieces))
(set draggingSprite s)
(set draggingLastPos (new FlxPoint s.x s.y))))
(set s.mouseStopDragCallback
->:Void [s x y]
(let [s (cast s KissExtendedSprite)]
(set draggingSprite null)
(let [connectedPieces (.concat (s.connectedAndSelectedSprites) [s])]
(doFor connected connectedPieces
(checkMatches (dictGet indexMap connected)))
(doFor connected connectedPieces
(dictSet (the Map<Int,FlxPoint> save.data.storedPositions) (dictGet indexMap connected) (new FlxPoint connected.x connected.y))))
(pieceCamera.calculateScrollBounds rewardSprites uiCamera SCROLL_BOUND_MARGIN)
(save.flush)))
(var ROT_PADDING 4)
(localVar fWidth (+ (Std.int sourceRect.width) (* 2 ROT_PADDING)))
(localVar fHeight (+ (Std.int sourceRect.height) (* 2 ROT_PADDING)))
(source.makeGraphic fWidth fHeight FlxColor.TRANSPARENT true)
(source.pixels.copyPixels rewardSprite.pixels sourceRect (new Point ROT_PADDING ROT_PADDING))
(mask.makeGraphic fWidth fHeight FlxColor.TRANSPARENT true)
(drawPieceShape mask jig ros FlxColor.BLACK)
(localVar unhighlightedS (new FlxSprite))
(FlxSpriteUtil.alphaMask unhighlightedS source.pixels mask.pixels)
(localVar highlightedS (new FlxSprite))
(s.loadGraphic unhighlightedS.pixels)
(highlightedS.loadGraphic unhighlightedS.pixels false 0 0 true)
(drawPieceShape highlightedS jig ros FlxColor.TRANSPARENT FlxColor.LIME)
(localFunction loadRotatedGraphic [:FlxSprite _s]
(s.loadRotatedGraphic _s.pixels 4 -1))
(loadRotatedGraphic unhighlightedS)
(s.enableDragToSelect
->:Void {
(loadRotatedGraphic highlightedS)
}
->:Void {
(loadRotatedGraphic unhighlightedS)
})
(set s.cameras [pieceCamera])
(rewardSprites.add s))))
(prop &mut :FlxBar bar null)
(prop &mut :FlxAsyncLoop asyncLoop null)
(set bar (new FlxBar 0 0 LEFT_TO_RIGHT (iThird FlxG.width) SimpleWindow.textSize rewardSprites "length" 0 piecesUnlocked true))
(set bar.cameras [uiCamera])
(set asyncLoop (new FlxAsyncLoop newPieces makeJig 1))
(bar.createColoredEmptyBar (FlxColor.LIME.getDarkened) true FlxColor.LIME)
(bar.createColoredFilledBar FlxColor.LIME false)
(bar.screenCenter)
(set bar.filledCallback ->:Void {
(remove bar)
(remove asyncLoop)
(rewardSprites.revive)
(doFor row (range PUZZLE_HEIGHT)
(doFor col (range PUZZLE_WIDTH)
(let [id (nth indexGrid row col)]
(when (= id -1) (continue))
(when (>= (- col 1) 0)
(let [toLeft (nth spriteGrid row (- col 1))]
(dictSet matchingPiecesLeft id toLeft)))
(when (< (+ col 1) PUZZLE_WIDTH)
(let [toRight (nth spriteGrid row (+ col 1))]
(dictSet matchingPiecesRight id toRight)))
(when (>= (- row 1) 0)
(let [toUp (nth spriteGrid (- row 1) col)]
(dictSet matchingPiecesUp id toUp)))
(when (< (+ row 1) PUZZLE_HEIGHT)
(let [toDown (nth spriteGrid (+ row 1) col)]
(dictSet matchingPiecesDown id toDown))))))
(doFor i (range TOTAL_PIECES)
(checkMatches i))
(pieceCamera.calculateScrollBounds rewardSprites uiCamera SCROLL_BOUND_MARGIN)
(when save.data.zoom
(set pieceCamera.zoom save.data.zoom)
(set pieceCamera.scroll save.data.scroll))
(set bar null)
(set asyncLoop null)
})
(add bar)
(add asyncLoop)
(asyncLoop.start)))
(set lastRewardFileIndex rewardFileIndex)
(prop &mut lastTotalPoints -1)
(set lastTotalPoints (m.totalPoints))
(set pieceCamera.bgColor (nth backgroundOptions save.data.backgroundIndex))
(save.flush))
(method makeText [:Entry e]
(let [label (HabitModel.activeLabel e)]
(_makeText label.label label.points ->:Void text {
(model.addPoint e)
(setModel model)
})))
// TODO configurable text size
(method _makeText [:String s :Int points &opt :Action action]
(entryWindow.makeText (+ s (HabitModel.pointsStr points)) action))
(method :Void log [:String message]
(trace message)
(when (> message.length (defAndReturn var FLX_LOG_MAX 100)) (set message (message.substr FLX_LOG_MAX)))
(prop &mut logTextY 0)
(#when debug
(when (> logTextY FlxG.height)
(logTexts.clear)
(set logTextY 0))
(let [text (new FlxText FlxG.width logTextY 0 message textSize)]
(set text.color FlxColor.LIME)
(set text.cameras [uiCamera])
(+= logTextY text.height)
(-= text.x text.width)
(logTexts.add text))))
(method :FlxRect matchZone [:KissExtendedSprite s compass]
(assertLet [id (dictGet indexMap s)
jig (dictGet pieceData id)]
(let [bubblePoints (dictGet jig.bubblePoints compass)]
(unless bubblePoints
(return (new FlxRect 0 0 0 0)))
(let [ros (roughOptimalScale)
pointsX (for point bubblePoints point.x)
pointsY (for point bubblePoints point.y)
minX (/ (apply min pointsX) ros)
minY (/ (apply min pointsY) ros)
maxX (/ (apply max pointsX) ros)
maxY (/ (apply max pointsY) ros)
tlc (.add (new FlxPoint minX minY) ROT_PADDING ROT_PADDING)
brc (.add (new FlxPoint maxX maxY) ROT_PADDING ROT_PADDING)
rotationPadding (s.getRotationPadding)
rect (.fromTwoPoints (new FlxRect) (tlc.addPoint rotationPadding) (brc.addPoint rotationPadding))
originOffset (new FlxPoint (- s.origin.x rect.x) (- s.origin.y rect.y))
rotated (rect.getRotatedBounds s.angle originOffset)]
(+= rotated.x s.x)
(+= rotated.y s.y)
rotated))))
(method :FlxRect matchZoneLeft [:KissExtendedSprite s]
(matchZone s WEST))
(method :FlxRect matchZoneRight [:KissExtendedSprite s]
(matchZone s EAST))
(method :FlxRect matchZoneUp [:KissExtendedSprite s]
(matchZone s NORTH))
(method :FlxRect matchZoneDown [:KissExtendedSprite s]
(matchZone s SOUTH))
(prop &mut c 0)
(method :Bool connectPiece [id self toSprite selfMatchZone toSpriteMatchZone]
(let [thisConnectedPieces (dictGet connectedPieces id)
toConnectedPieces (dictGet connectedPieces (dictGet indexMap toSprite))]
// Don't add duplicates or snap for pieces alread connected
(when (contains thisConnectedPieces toSprite)
(return false))
(+= c 1)
// Snap the pieces together
(let [offsetX (- toSpriteMatchZone.x selfMatchZone.x)
offsetY (- toSpriteMatchZone.y selfMatchZone.y)
selfAndAttached (recursivelyConnectedPieces self)
indices (for s selfAndAttached (dictGet indexMap s))
otherAndAttached (recursivelyConnectedPieces toSprite)
otherIndices (for s otherAndAttached (dictGet indexMap s))]
//(print "attaching $indices to $otherIndices")
(doFor piece selfAndAttached
(+= piece.x offsetX)
(+= piece.y offsetY))
// TODO check for matches created by snapping all the pieces?
// Or is it fine not to?
)
(thisConnectedPieces.push toSprite)
(toConnectedPieces.push self)
(let [selfAndAttached (recursivelyConnectedPieces self)]
(doFor s selfAndAttached
(set s.connectedSprites selfAndAttached)))
true))
(defMacro _checkMatch [side otherSide]
(let [sideStr (symbolNameValue side)
otherSideStr (symbolNameValue otherSide)
to (symbol "to$sideStr")
mp (symbol "matchingPieces$sideStr")
mz1 (symbol "matchZone$sideStr")
mz2 (symbol "matchZone$otherSideStr")]
`(whenLet [,to (dictGet ,mp id)
mz1 (,mz1 s)
mz2 (,mz2 ,to)]
(unless (or !(= s.angle .angle ,to) .isEmpty (mz1.intersection mz2))
(connectPiece id s ,to mz1 mz2)))))
(method :Bool checkMatches [id]
(when !(pieceData.exists id)
(return false))
(let [s (dictGet spriteMap id)
jig (dictGet pieceData id)
row jig.row
col jig.col]
(_checkMatch Left Right)
(_checkMatch Right Left)
(_checkMatch Up Down)
(_checkMatch Down Up))
false)
(method :Array<KissExtendedSprite> recursivelyConnectedPieces [s &opt :Array<KissExtendedSprite> collected]
(unless collected (set collected [s]))
(whenLet [directlyConnected (dictGet connectedPieces (dictGet indexMap s))]
(doFor piece directlyConnected
(unless (contains collected piece)
(collected.push piece)
(recursivelyConnectedPieces piece collected))))
collected)
(prop &mut :FlxGroup nextPuzzleChoiceGroup null)
(method :Void startPuzzlePackChoice [nextStartingPoints]
(when rewardSprites (rewardSprites.kill))
(when entryWindow (entryWindow.hide))
(set puzzlePackChoiceWindow (SimpleWindow.promptForChoice "Choose a puzzle pack:"
(PuzzlePack.availablePacks model)
->[:PuzzlePack pack] (ifLet [(Some np) pack.nextPuzzle]
(startPuzzleSizeChoice
->[chosenSize pointsPerPiece]
(let [bmd (BitmapData.fromFile np.path)
aspectRatioX (/ bmd.width bmd.height)
aspectRatioY (/ bmd.height bmd.width)
w (max 1 (Math.round (* aspectRatioX chosenSize)))
h (max 1 (Math.round (* aspectRatioY chosenSize)))]
(model.addRewardFile np.path nextStartingPoints w h pointsPerPiece)
(setModel model)
(entryWindow.show)))
(startPuzzlePackChoice nextStartingPoints))
null null FlxColor.LIME null 0.9)))
(var MIN_PUZZLE_SIZE 5)
(var MAX_PUZZLE_SIZE 32)
(var PUZZLE_SIZE_OPTIONS (collect (range MIN_PUZZLE_SIZE MAX_PUZZLE_SIZE 2)))
(method :Void startPuzzleSizeChoice [:StartPuzzleFunc startPuzzle]
(set puzzlePackChoiceWindow (SimpleWindow.promptForChoice "Approx. # of Pieces:"
// TODO also limit puzzle size by rewardSprite dimensions (which are available in bmd in startPuzzlePackChoice())
(for size PUZZLE_SIZE_OPTIONS (* size size))
->:Void [:Int size] (startPiecesPerPointChoice (Std.int (Math.sqrt size)) startPuzzle)
null null FlxColor.LIME null 0.9)))
(method :Void startPiecesPerPointChoice [size :StartPuzzleFunc startPuzzle]
(let [maxPPP (Math.round (/ (* size size) (* MIN_PUZZLE_SIZE MIN_PUZZLE_SIZE)))]
(when (= maxPPP 1)
(startPuzzle size 1)
(return))
(set puzzlePackChoiceWindow (SimpleWindow.promptForChoice "# of pieces to unlock per habit point:"
(collect (range 1 maxPPP))
->:Void [:Int points] (startPuzzle size points)
null null FlxColor.LIME null 0.9))))
(method createToggleIndicesType [defEnabled constructor :Array<String> days negativeStart prompt &opt width height]
(let [daysEnabled (for day days defEnabled)
daysEnabledModelFormat ->(let [:Array<Int> idxArr []]
(doFor [idx day] (enumerate daysEnabled) (when day (idxArr.push
(if (>= idx negativeStart)
(- -1 (- idx negativeStart))
(+ idx 1)))))
idxArr)
dayText ->idx "$(nth days idx): $(if (nth daysEnabled idx) "yes" "no")"
dayColor ->idx (if (nth daysEnabled idx) (FlxColor.LIME.getDarkened) FlxColor.GRAY)
window (new SimpleWindow prompt null null width height true xKey leftKey rightKey backToEntryWindow)]
(localFunction refreshWindow []
(window.clearControls)
(doFor [idx day] (enumerate days)
(window.makeText (dayText idx) (dayColor idx) ->:Void _ {
(setNth daysEnabled idx !(nth daysEnabled idx))
(refreshWindow)
}))
(window.makeText "Confirm" FlxColor.LIME ->:Void _
(when (daysEnabledModelFormat)
(window.hide)
(startAdding (constructor (daysEnabledModelFormat) "")))))
(set entryCreationWindow window)
(refreshWindow)
(window.show)))
(method createDailyEntry []
(createToggleIndicesType true Daily ["Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday" "Sunday"] 8 "Which days of the week?"))
(method createMonthlyEntry []
(let [texts
(concat
(for d (range 28) "Day $(+ d 1)")
(for d (range 28) "$(+ d 1) days before month ends"))]
(createToggleIndicesType false Monthly (cast texts) 28 "Which days of the month?" 0.9 0.9)))
(method createIntervalEntry []
(set entryCreationWindow (new SimpleWindow "After finishing this habit, how many days do you wait before doing it again?" null null 0.9 0.9 true xKey leftKey rightKey backToEntryWindow))
(set entryNameText (new KissInputText 0 0 FlxG.width "" textSize true))
(set addingLabels false)
(entryCreationWindow.addControl entryNameText)
(entryCreationWindow.makeText "Confirm" FlxColor.LIME
->:Void _
(defAndCall method startAddingInterval
(try
(let [int (Std.parseInt entryNameText.text)]
(entryNameText.kill)
(set entryNameText null)
(entryCreationWindow.hide)
(startAdding (Interval int "")))
(catch [e] (return)))))
(entryCreationWindow.show))
(method createTaskEntry [] (startAdding Todo))
(method createBonusEntry [] (startAdding Bonus))
(method addCreatedEntry []
// addEntry() calls save()
(when (entryNameText.text.trim)
(labelsAdding.push entryNameText.text))
(unless labelsAdding
(return))
(model.addEntry typeAdding labelsAdding false) // TODO allow choosing priority!
(refreshModel)
(entryNameText.kill)
(set entryNameText null)
(entryCreationWindow.hide)
(when entryWindow
(set entryWindow.keyboardEnabled true)
(entryWindow.show)))
(defMacro withConnectedAndMatching [forOrDoFor &body body]
`(,forOrDoFor s rewardSprites.members
(let [id (dictGet indexMap s)
connectedPieces (dictGet connectedPieces id)
matchingPieces (filter (for map [matchingPiecesLeft matchingPiecesRight matchingPiecesUp matchingPiecesDown]
(dictGet map id)))]
,@body)))
(method countAvailableMatches []
(iHalf
(apply +
(withConnectedAndMatching for
(- matchingPieces.length connectedPieces.length)))))
(method :Array<Array<KissExtendedSprite>> listAvailableMatches []
(apply concat (the Array<Array<Array<KissExtendedSprite>>> (withConnectedAndMatching for
(for piece (filter matchingPieces ->p !(contains connectedPieces p))
[s piece])))))
(method editLabels [:Entry e]
(let [window (new SimpleWindow "Editing labels" null null 0.9 0.9 true xKey leftKey rightKey backToEntryWindow)
inputTexts (for l e.labels
(newNameInputText))]
// TODO allow adding more labels in between/before/at end
// TODO allow deleting labels (keep score?)
(doFor inputText inputTexts
(window.addControl inputText))
(window.makeText "Save" FlxColor.LIME ->:Void _
{
(set e.labels (for [inputText label] (zip inputTexts e.labels)
(object points label.points label inputText.text)))
(model.save)
(window.hide)
(backToEntryWindow)
})
(set entryEditWindow window)
(window.show)))

View File

@@ -0,0 +1,42 @@
package;
import sys.io.File;
import sys.FileSystem;
import flixel.FlxG;
import flixel.FlxGame;
import openfl.display.Sprite;
import flixel.util.FlxTimer;
import kiss.Prelude;
class Main extends Sprite
{
public function new()
{
super();
addChild(new FlxGame(0, 0, HabitState, 60, 60, true));
var t:HabitState = cast FlxG.state;
var saveFolder = Prelude.joinPath(Prelude.userHome(), "Documents", "HabitPuzzles");
var habitFile = Prelude.joinPath(saveFolder, "habits.txt");
if (!(FileSystem.exists(saveFolder) && FileSystem.isDirectory(saveFolder))) {
FileSystem.createDirectory(saveFolder);
}
if (!FileSystem.exists(habitFile)) {
File.saveContent(habitFile, File.getContent("assets/default.txt"));
}
function reloadModel(_) {
if (t.draggingSprite == null && !t.tempWindowIsShown()) {
var showLowerPriority = t.model.showLowerPriority;
var newModel = new HabitModel(habitFile);
newModel.showLowerPriority = showLowerPriority;
t.refreshModel(newModel);
t.model.save();
}
}
t.setModel(new HabitModel(habitFile));
new FlxTimer().start(30, reloadModel, 0);
}
}

View File

@@ -0,0 +1,10 @@
package;
import kiss.Prelude;
import kiss.List;
import haxe.ds.Option;
import sys.FileSystem;
import HabitModel;
@:build(kiss.Kiss.build())
class PuzzlePack { }

View File

@@ -0,0 +1,44 @@
(defNew [&prop :String path
&prop :Option<Puzzle> nextPuzzle
&prop :Int puzzlesDone
&prop :Int puzzlesTotal])
(var puzzleSearchGlobs ["puzzles"])
// TODO add the itch io client folder to search paths- it's
// C:\Users\$(userHome)\AppData\Roaming\itch\apps\ on windows
(function _glob [pattern]
// TODO implement my own "glob" to avoid haxe-concurrency dependency
[pattern])
(function :Array<PuzzlePack> availablePacks [:HabitModel model]
(let [:Array<PuzzlePack> packs []]
(doFor glob puzzleSearchGlobs
(doFor dir (_glob glob)
(let [packDirs (filter (for thing (FileSystem.readDirectory dir) (let [full "${dir}/${thing}"] (when (FileSystem.isDirectory full) full))))]
(doFor packDir packDirs
(let [fop (firstUnsolvedPuzzle model packDir)]
(packs.push
(new PuzzlePack
packDir
(if fop.path
(Some fop)
None)
fop.index
fop.outOf)))))))
packs))
(function :Puzzle firstUnsolvedPuzzle [:HabitModel model :String dir]
(let [images (FileSystem.readDirectory dir)
&mut puzzleCount images.length
rewardFilePaths (for rf model.rewardFiles rf.path)]
(doFor [idx image] (enumerate images)
(let [fullPath (joinPath dir image)]
(if (FileSystem.isDirectory fullPath)
(-= puzzleCount 1)
(unless (rewardFilePaths.contains fullPath)
(return (object path fullPath index idx outOf images.length))))))
(object path null index images.length outOf images.length)))
(method toString []
"$(haxe.io.Path.withoutDirectory path): ${puzzlesDone}/${puzzlesTotal}")

View File

@@ -0,0 +1,593 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
<!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
<!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
<!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
<!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
<!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
<!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
<!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
]>
<svg version="1.1" id="Layer_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="353.746px"
height="353.777px" viewBox="0 0 353.746 353.777" enable-background="new 0 0 353.746 353.777" xml:space="preserve">
<metadata>
<sfw xmlns="&ns_sfw;">
<slices></slices>
<sliceSourceBounds height="355.67" y="438.33" x="-63.62" width="491.91" bottomLeftOrigin="true"></sliceSourceBounds>
</sfw>
</metadata>
<g>
<g>
<polyline fill="#00B6B2" points="0,0 0,353.777 353.746,353.777 353.746,0 0,0 "/>
</g>
<path fill="#0095A8" d="M60.771,81.353H-49.356c-0.867-0.58-1.442-1.351-1.816-2.101c-0.749-1.507-0.741-2.943-0.745-2.993V8.695
c-0.001-1.461,0.371-2.614,0.953-3.483c0.58-0.871,1.353-1.447,2.104-1.822c1.507-0.749,2.943-0.741,2.993-0.745V3.25v0.605
l-0.019,0l-0.084,0.003c-0.075,0.004-0.188,0.012-0.33,0.028c-0.283,0.032-0.68,0.099-1.116,0.23
c-0.877,0.263-1.884,0.777-2.541,1.766c-0.44,0.662-0.748,1.551-0.75,2.812v67.564l0.001,0.02l0.003,0.083
c0.004,0.076,0.012,0.189,0.028,0.33c0.033,0.283,0.099,0.68,0.23,1.116c0.263,0.877,0.777,1.885,1.766,2.542
c0.662,0.439,1.551,0.747,2.812,0.749H57.39l0.02-0.001l0.083-0.003c0.075-0.004,0.189-0.012,0.33-0.028
c0.283-0.033,0.68-0.099,1.116-0.23c0.877-0.263,1.885-0.777,2.542-1.766c0.439-0.662,0.747-1.551,0.749-2.812V8.695l-0.001-0.02
l-0.003-0.083c-0.004-0.075-0.012-0.188-0.028-0.33c-0.033-0.283-0.099-0.68-0.23-1.116c-0.263-0.877-0.777-1.885-1.766-2.542
c-0.662-0.44-1.551-0.748-2.812-0.749H-45.867V3.25V2.645H57.39c0.003,0,0.006,0,0.009,0c1.456,0,2.607,0.372,3.474,0.953
c0.871,0.58,1.447,1.353,1.822,2.104c0.749,1.507,0.742,2.943,0.745,2.993v67.564c0.002,1.461-0.371,2.614-0.953,3.484
C62.007,80.464,61.395,80.983,60.771,81.353"/>
<path fill="#0095A8" d="M-63.069,88.454c-0.346,0-0.662-0.095-0.904-0.258c-0.245-0.163-0.405-0.381-0.502-0.577
c-0.193-0.395-0.186-0.72-0.189-0.77v-3.891c-0.002-0.35,0.093-0.67,0.258-0.914c0.163-0.246,0.381-0.405,0.576-0.502
c0.396-0.193,0.72-0.186,0.771-0.189v0.605v0.605v-0.605v-0.605h13.703H60.771h13.811c0.004,0,0.007,0,0.01,0
c0.346,0,0.662,0.095,0.904,0.258c0.246,0.163,0.405,0.38,0.503,0.576c0.192,0.396,0.185,0.72,0.188,0.771v3.891
c0.002,0.35-0.093,0.669-0.257,0.914c-0.164,0.245-0.381,0.405-0.577,0.502c-0.396,0.193-0.72,0.186-0.771,0.189H-63.059
C-63.062,88.454-63.065,88.454-63.069,88.454 M74.574,87.244h0.002l0.029-0.003l0.12-0.024c0.096-0.029,0.166-0.075,0.198-0.126
c0.023-0.037,0.053-0.092,0.054-0.242v-3.883v-0.002l-0.002-0.029l-0.025-0.12c-0.029-0.096-0.074-0.166-0.125-0.198
c-0.037-0.022-0.092-0.053-0.243-0.054H-63.052l-0.03,0.002l-0.12,0.025c-0.095,0.029-0.165,0.074-0.197,0.125
c-0.023,0.037-0.053,0.092-0.055,0.243v3.884l0.003,0.03l0.024,0.119c0.029,0.096,0.074,0.166,0.125,0.198
c0.037,0.023,0.093,0.053,0.243,0.055H74.574"/>
<path fill="#0095A8" d="M-40.484,73.974c-1.456,0-2.606-0.372-3.473-0.952c-0.871-0.581-1.447-1.353-1.822-2.105
c-0.748-1.507-0.741-2.943-0.744-2.993V14.938c-0.002-1.461,0.371-2.614,0.952-3.483c0.58-0.871,1.353-1.447,2.105-1.822
c1.507-0.748,2.942-0.741,2.993-0.745v0.605v0.605l-0.02,0l-0.084,0.003c-0.075,0.004-0.188,0.012-0.329,0.028
c-0.283,0.033-0.68,0.099-1.116,0.23c-0.878,0.263-1.885,0.777-2.542,1.766c-0.44,0.662-0.748,1.551-0.749,2.812v52.986v0.02
l0.003,0.084c0.004,0.075,0.012,0.188,0.029,0.329c0.032,0.283,0.098,0.68,0.229,1.116c0.263,0.877,0.778,1.885,1.766,2.542
c0.662,0.439,1.551,0.747,2.813,0.749h92.47h0.02L52.1,72.76c0.075-0.004,0.188-0.012,0.33-0.028
c0.283-0.033,0.68-0.099,1.116-0.23c0.877-0.263,1.884-0.777,2.542-1.766c0.439-0.662,0.747-1.55,0.749-2.812V14.938l-0.001-0.02
l-0.003-0.083c-0.004-0.075-0.012-0.188-0.028-0.33c-0.033-0.283-0.099-0.68-0.23-1.116c-0.263-0.877-0.777-1.884-1.766-2.541
c-0.662-0.44-1.551-0.748-2.812-0.749h-92.47V9.493V8.888h92.47c0.003,0,0.006,0,0.009,0c1.456,0,2.607,0.372,3.474,0.953
c0.871,0.58,1.447,1.353,1.822,2.104c0.749,1.507,0.742,2.943,0.745,2.993v52.986c0.002,1.461-0.371,2.614-0.953,3.484
c-0.58,0.87-1.353,1.446-2.104,1.822c-1.507,0.748-2.943,0.741-2.993,0.744h-92.47C-40.477,73.974-40.48,73.974-40.484,73.974"/>
<path fill="#0095A8" d="M199.174,339.553H89.047c-0.867-0.579-1.441-1.35-1.816-2.1c-0.748-1.507-0.741-2.943-0.744-2.993v-67.564
c-0.002-1.461,0.371-2.614,0.952-3.483c0.58-0.871,1.353-1.447,2.105-1.822c1.507-0.749,2.942-0.742,2.993-0.745v0.605v0.605h-0.02
l-0.084,0.004c-0.075,0.004-0.188,0.012-0.329,0.028c-0.283,0.033-0.68,0.099-1.116,0.23c-0.878,0.263-1.885,0.777-2.542,1.766
c-0.44,0.662-0.748,1.551-0.749,2.812v67.564v0.02l0.003,0.083c0.004,0.075,0.012,0.188,0.029,0.33
c0.032,0.283,0.098,0.68,0.229,1.116c0.264,0.877,0.778,1.885,1.766,2.542c0.662,0.439,1.551,0.747,2.813,0.749h103.256l0.02-0.001
l0.084-0.003c0.075-0.004,0.188-0.012,0.329-0.028c0.283-0.033,0.68-0.099,1.116-0.23c0.877-0.263,1.885-0.777,2.542-1.766
c0.439-0.662,0.747-1.551,0.749-2.812v-67.564v-0.02l-0.003-0.083c-0.005-0.076-0.012-0.188-0.029-0.33
c-0.032-0.283-0.099-0.68-0.229-1.116c-0.264-0.877-0.778-1.885-1.766-2.542c-0.663-0.439-1.551-0.747-2.813-0.749H92.537v-0.605
v-0.605h103.256c0.004,0,0.007,0,0.011,0c1.456,0,2.605,0.372,3.473,0.953c0.87,0.58,1.447,1.352,1.822,2.104
c0.748,1.507,0.741,2.943,0.744,2.993v67.564c0.002,1.461-0.371,2.614-0.952,3.483C200.41,338.664,199.798,339.183,199.174,339.553
"/>
<path fill="#0095A8" d="M75.334,346.655c-0.345,0-0.662-0.095-0.904-0.258c-0.245-0.164-0.404-0.381-0.502-0.577
c-0.193-0.396-0.186-0.72-0.189-0.77v-3.891c-0.002-0.35,0.093-0.67,0.258-0.914c0.164-0.246,0.381-0.405,0.577-0.503
c0.396-0.192,0.72-0.185,0.77-0.189v0.605v0.605v-0.605v-0.605h13.703h110.127h13.812c0.003,0,0.006,0,0.009,0
c0.346,0,0.662,0.095,0.904,0.258c0.246,0.164,0.405,0.381,0.503,0.577c0.193,0.396,0.185,0.72,0.189,0.771v3.891
c0.001,0.349-0.093,0.669-0.258,0.913c-0.164,0.246-0.381,0.405-0.577,0.503c-0.396,0.192-0.72,0.185-0.77,0.189H75.344
C75.341,346.655,75.338,346.655,75.334,346.655 M74.949,345.043l0.003,0.03l0.024,0.119c0.029,0.096,0.075,0.166,0.126,0.198
c0.037,0.023,0.092,0.053,0.242,0.055h137.635l0.029-0.003l0.12-0.025c0.096-0.028,0.166-0.074,0.198-0.125
c0.023-0.037,0.053-0.092,0.055-0.242v-3.883v-0.002l-0.003-0.03l-0.025-0.119c-0.029-0.096-0.074-0.166-0.125-0.198
c-0.037-0.023-0.092-0.053-0.242-0.055H75.353h-0.002l-0.03,0.003l-0.119,0.025c-0.096,0.029-0.166,0.074-0.198,0.125
c-0.023,0.037-0.053,0.092-0.055,0.243V345.043"/>
<path fill="#0095A8" d="M97.921,332.175c-1.457,0-2.607-0.372-3.475-0.953c-0.87-0.58-1.446-1.352-1.822-2.104
c-0.748-1.507-0.741-2.943-0.744-2.993v-52.986c-0.002-1.461,0.371-2.614,0.952-3.483c0.58-0.871,1.353-1.447,2.105-1.822
c1.507-0.749,2.942-0.742,2.993-0.745v0.605v0.605h-0.02l-0.083,0.004c-0.076,0.004-0.189,0.012-0.33,0.028
c-0.283,0.033-0.68,0.099-1.116,0.23c-0.877,0.263-1.885,0.777-2.542,1.766c-0.44,0.662-0.747,1.551-0.749,2.812v52.986v0.02
l0.004,0.083c0.003,0.075,0.011,0.188,0.028,0.33c0.032,0.283,0.098,0.68,0.23,1.116c0.263,0.877,0.777,1.885,1.766,2.542
c0.662,0.439,1.55,0.747,2.812,0.749h92.47l0.02-0.001l0.083-0.003c0.076-0.004,0.189-0.012,0.33-0.028
c0.283-0.033,0.68-0.099,1.116-0.23c0.877-0.263,1.885-0.777,2.542-1.766c0.439-0.662,0.747-1.551,0.749-2.812v-52.986v-0.02
l-0.004-0.083c-0.004-0.076-0.012-0.188-0.028-0.33c-0.032-0.283-0.099-0.68-0.23-1.116c-0.263-0.877-0.777-1.885-1.766-2.542
c-0.662-0.439-1.55-0.747-2.812-0.749H97.93v-0.605v-0.605h92.47c0.004,0,0.007,0,0.011,0c1.456,0,2.605,0.372,3.472,0.953
c0.871,0.58,1.447,1.352,1.822,2.104c0.749,1.507,0.742,2.943,0.745,2.993v52.986c0.002,1.461-0.371,2.614-0.952,3.483
c-0.58,0.871-1.353,1.447-2.105,1.822c-1.507,0.749-2.942,0.741-2.993,0.745H97.93C97.927,332.175,97.924,332.175,97.921,332.175"
/>
<path fill="#6BC9C7" d="M240.155,337.441c-2.817,0-4.987-0.713-6.62-1.804c-1.637-1.09-2.723-2.543-3.439-3.976
c-1.429-2.868-1.422-5.665-1.425-5.715v-66.375c-0.002-2.822,0.711-4.996,1.803-6.631c1.091-1.637,2.544-2.723,3.977-3.439
c2.868-1.429,5.665-1.422,5.715-1.425v0.605v0.605l-0.055,0.001l-0.183,0.007c-0.162,0.009-0.401,0.026-0.698,0.06
c-0.594,0.068-1.421,0.207-2.336,0.481c-1.834,0.55-3.99,1.639-5.413,3.776c-0.95,1.428-1.598,3.337-1.6,5.96V307.1h-0.741v1.21
h0.741v5.179h-0.741v1.21h0.741v4.725h-0.741v1.21h0.741v4.725h-0.741v1.21h0.777c0.008,0.095,0.019,0.199,0.032,0.312
c0.068,0.594,0.206,1.422,0.481,2.337c0.55,1.834,1.639,3.99,3.776,5.413c1.428,0.95,3.337,1.598,5.96,1.6h28.099l0.055-0.001
l0.183-0.007c0.162-0.009,0.4-0.026,0.698-0.06c0.594-0.069,1.421-0.207,2.335-0.481c1.835-0.551,3.991-1.639,5.414-3.776
c0.873-1.312,1.491-3.031,1.587-5.337h0.754v-1.21h-0.741v-4.725h0.741v-1.21h-0.741v-4.725h0.741v-1.21h-0.741v-5.179h0.741v-1.21
h-0.741v-47.529l-0.001-0.055l-0.007-0.183c-0.009-0.162-0.026-0.4-0.06-0.697c-0.068-0.595-0.207-1.422-0.481-2.337
c-0.55-1.834-1.639-3.99-3.776-5.413c-1.428-0.95-3.337-1.598-5.96-1.6h-28.099v-0.605v-0.605h28.099c0.004,0,0.007,0,0.011,0
c2.817,0,4.987,0.713,6.62,1.803c1.637,1.091,2.723,2.544,3.439,3.977c1.429,2.868,1.422,5.665,1.425,5.715v66.375
c0.002,2.822-0.712,4.996-1.803,6.631c-1.091,1.636-2.544,2.723-3.977,3.439c-2.868,1.429-5.665,1.421-5.715,1.425h-28.099
C240.162,337.441,240.159,337.441,240.155,337.441"/>
<path fill="#6BC9C7" d="M240.552,331.941c-2.648,0-4.439-1.023-5.531-2.319c-0.844-0.995-1.296-2.118-1.543-3.053h1.258
c0.229,0.74,0.604,1.564,1.206,2.269c0.705,0.817,1.695,1.506,3.222,1.774v0.28h1.21v-0.164c0.07,0.002,0.141,0.003,0.212,0.003
h4.023v0.161h1.21v-0.161h3.328v0.161h1.21v-0.161h3.781v0.161h1.21v-0.161h3.781v0.161h1.21v-0.161h3.328v1.059h1.21v-1.059h3.388
h0.024l0.095-0.004c0.066-0.003,0.159-0.009,0.274-0.019v0.184h1.21v-0.391c0.053-0.013,0.107-0.027,0.161-0.042
c1.015-0.273,2.232-0.816,3.12-1.86c0.449-0.528,0.825-1.185,1.059-2.03h1.249c-0.268,1.16-0.768,2.092-1.387,2.816
c-0.74,0.866-1.637,1.436-2.492,1.811c-1.712,0.747-3.266,0.743-3.313,0.745h-27.679
C240.575,331.941,240.563,331.941,240.552,331.941"/>
<polyline fill="#6BC9C7" points="279.291,308.31 278.55,308.31 275.767,308.31 275.767,307.705 274.557,307.705 274.557,308.31
269.868,308.31 269.868,308.159 268.658,308.159 268.658,308.31 264.877,308.31 264.877,307.787 263.667,307.787 263.667,308.31
260.339,308.31 260.339,307.787 259.129,307.787 259.129,308.31 255.348,308.31 255.348,307.787 254.138,307.787 254.138,308.31
250.357,308.31 250.357,307.705 249.147,307.705 249.147,308.31 245.819,308.31 245.819,307.705 244.609,307.705 244.609,308.31
240.374,308.31 240.374,307.787 239.164,307.787 239.164,308.31 234.929,308.31 234.929,308.159 233.719,308.159 233.719,308.31
229.881,308.31 229.14,308.31 229.14,307.1 229.881,307.1 278.55,307.1 279.291,307.1 279.291,308.31 "/>
<path fill="#6BC9C7" d="M279.291,314.699h-0.741h-2.783v-1.21h2.783h0.741V314.699 M274.557,314.699h-4.689v-1.21h4.689V314.699
M268.658,314.699h-3.781v-1.21h3.781V314.699 M263.667,314.699h-3.328v-1.21h3.328V314.699 M259.129,314.699h-3.781v-1.21h3.781
V314.699 M254.138,314.699h-3.781v-1.21h3.781V314.699 M249.147,314.699h-3.328v-1.21h3.328V314.699 M244.609,314.699h-4.235v-1.21
h4.235V314.699 M239.164,314.699h-4.235v-1.21h4.235V314.699 M233.719,314.699h-3.838h-0.741v-1.21h0.741h3.838V314.699"/>
<path fill="#6BC9C7" d="M279.291,320.634h-0.741h-2.783v-1.21h2.783h0.741V320.634 M274.557,320.634h-4.689v-1.21h4.689V320.634
M268.658,320.634h-3.781v-1.21h3.781V320.634 M263.667,320.634h-3.328v-1.21h3.328V320.634 M259.129,320.634h-3.781v-1.21h3.781
V320.634 M254.138,320.634h-3.781v-1.21h3.781V320.634 M249.147,320.634h-3.328v-1.21h3.328V320.634 M244.609,320.634h-4.235v-1.21
h4.235V320.634 M239.164,320.634h-4.235v-1.21h4.235V320.634 M233.719,320.634h-3.838h-0.741v-1.21h0.741h3.838V320.634"/>
<path fill="#6BC9C7" d="M279.291,326.569h-0.754h-3.08h-1.249h-4.34v-1.21h4.689v1.058h1.21v-1.058h2.783h0.741V326.569
M268.658,326.569h-3.781v-1.21h3.781V326.569 M263.667,326.569h-3.328v-1.21h3.328V326.569 M259.129,326.569h-3.781v-1.21h3.781
V326.569 M254.138,326.569h-3.781v-1.21h3.781V326.569 M249.147,326.569h-3.328v-1.21h3.328V326.569 M244.609,326.569h-4.235v-1.21
h4.235V326.569 M239.164,326.569h-4.428h-1.258h-3.561h-0.777v-1.21h0.741h3.838v0.605h1.21v-0.605h4.235V326.569"/>
<path fill="#6BC9C7" d="M277.309,305.633H231.94V261.74v-0.605h45.369V305.633 M233.15,262.345v42.078h42.95v-42.078H233.15
M232.545,261.74v0.605V261.74"/>
<polyline fill="#6BC9C7" points="234.929,325.964 233.719,325.964 233.719,325.359 233.719,320.634 233.719,319.424
233.719,314.699 233.719,313.489 233.719,308.31 233.719,308.159 234.929,308.159 234.929,308.31 234.929,313.489 234.929,314.699
234.929,319.424 234.929,320.634 234.929,325.359 234.929,325.964 "/>
<polyline fill="#6BC9C7" points="240.374,330.892 239.164,330.892 239.164,330.612 239.164,326.569 239.164,325.359
239.164,320.634 239.164,319.424 239.164,314.699 239.164,313.489 239.164,308.31 239.164,307.787 240.374,307.787 240.374,308.31
240.374,313.489 240.374,314.699 240.374,319.424 240.374,320.634 240.374,325.359 240.374,326.569 240.374,330.728
240.374,330.892 "/>
<polyline fill="#6BC9C7" points="245.819,330.892 244.609,330.892 244.609,330.731 244.609,326.569 244.609,325.359
244.609,320.634 244.609,319.424 244.609,314.699 244.609,313.489 244.609,308.31 244.609,307.705 245.819,307.705 245.819,308.31
245.819,313.489 245.819,314.699 245.819,319.424 245.819,320.634 245.819,325.359 245.819,326.569 245.819,330.731
245.819,330.892 "/>
<polyline fill="#6BC9C7" points="250.357,330.892 249.147,330.892 249.147,330.731 249.147,326.569 249.147,325.359
249.147,320.634 249.147,319.424 249.147,314.699 249.147,313.489 249.147,308.31 249.147,307.705 250.357,307.705 250.357,308.31
250.357,313.489 250.357,314.699 250.357,319.424 250.357,320.634 250.357,325.359 250.357,326.569 250.357,330.731
250.357,330.892 "/>
<polyline fill="#6BC9C7" points="255.348,330.892 254.138,330.892 254.138,330.731 254.138,326.569 254.138,325.359
254.138,320.634 254.138,319.424 254.138,314.699 254.138,313.489 254.138,308.31 254.138,307.787 255.348,307.787 255.348,308.31
255.348,313.489 255.348,314.699 255.348,319.424 255.348,320.634 255.348,325.359 255.348,326.569 255.348,330.731
255.348,330.892 "/>
<polyline fill="#6BC9C7" points="260.339,330.892 259.129,330.892 259.129,330.731 259.129,326.569 259.129,325.359
259.129,320.634 259.129,319.424 259.129,314.699 259.129,313.489 259.129,308.31 259.129,307.787 260.339,307.787 260.339,308.31
260.339,313.489 260.339,314.699 260.339,319.424 260.339,320.634 260.339,325.359 260.339,326.569 260.339,330.731
260.339,330.892 "/>
<polyline fill="#6BC9C7" points="264.877,331.79 263.667,331.79 263.667,330.731 263.667,326.569 263.667,325.359 263.667,320.634
263.667,319.424 263.667,314.699 263.667,313.489 263.667,308.31 263.667,307.787 264.877,307.787 264.877,308.31 264.877,313.489
264.877,314.699 264.877,319.424 264.877,320.634 264.877,325.359 264.877,326.569 264.877,330.731 264.877,331.79 "/>
<polyline fill="#6BC9C7" points="269.868,330.892 268.658,330.892 268.658,330.708 268.658,326.569 268.658,325.359
268.658,320.634 268.658,319.424 268.658,314.699 268.658,313.489 268.658,308.31 268.658,308.159 269.868,308.159 269.868,308.31
269.868,313.489 269.868,314.699 269.868,319.424 269.868,320.634 269.868,325.359 269.868,326.569 269.868,330.501
269.868,330.892 "/>
<polyline fill="#6BC9C7" points="275.767,326.417 274.557,326.417 274.557,325.359 274.557,320.634 274.557,319.424
274.557,314.699 274.557,313.489 274.557,308.31 274.557,307.705 275.767,307.705 275.767,308.31 275.767,313.489 275.767,314.699
275.767,319.424 275.767,320.634 275.767,325.359 275.767,326.417 "/>
<path fill="#6BC9C7" d="M22.901,197.312h-50.483c-0.011-0.111-0.017-0.204-0.02-0.275l-0.005-0.125l-0.001-0.034v-0.776H22.91
v0.776C22.91,197.026,22.906,197.171,22.901,197.312"/>
<path fill="#6BC9C7" d="M22.91,109.956h-50.518v-0.425c0-0.273,0.011-0.535,0.03-0.785h50.423c0.007,0.049,0.013,0.097,0.018,0.143
c0.024,0.206,0.035,0.371,0.041,0.483l0.005,0.125l0.001,0.034V109.956"/>
<path fill="#6BC9C7" d="M20.336,189.997h-45.37V117.45v-0.605h45.37V189.997 M-23.824,118.055v70.732h42.95v-70.732H-23.824
M-24.429,117.45v0.605V117.45"/>
<path fill="#6BC9C7" d="M-20.508,205.197c-2.024,0-3.6-0.514-4.786-1.307c-1.19-0.793-1.979-1.849-2.496-2.885
c-1.032-2.074-1.025-4.077-1.028-4.127v-87.347c-0.002-2.028,0.513-3.607,1.307-4.795c0.793-1.19,1.849-1.979,2.885-2.496
c2.074-1.031,4.076-1.024,4.127-1.028v0.605v0.605l-0.034,0.001l-0.126,0.005c-0.111,0.006-0.276,0.017-0.483,0.041
c-0.412,0.048-0.988,0.144-1.624,0.335c-1.276,0.383-2.762,1.136-3.738,2.603c-0.555,0.835-0.963,1.91-1.074,3.339
c-0.019,0.25-0.03,0.512-0.03,0.785v0.425v86.146v0.776l0.001,0.034l0.005,0.125c0.003,0.071,0.009,0.164,0.02,0.275
c0.005,0.064,0.012,0.133,0.021,0.208c0.047,0.413,0.144,0.989,0.334,1.625c0.383,1.276,1.137,2.762,2.604,3.738
c0.981,0.652,2.295,1.102,4.124,1.104h36.3l0.034-0.001l0.125-0.005c0.112-0.006,0.277-0.017,0.483-0.041
c0.413-0.048,0.989-0.144,1.625-0.334c1.276-0.383,2.762-1.137,3.738-2.604c0.599-0.902,1.028-2.085,1.095-3.69
c0.005-0.141,0.009-0.286,0.009-0.434v-0.776v-86.146v-0.425l-0.001-0.034l-0.005-0.125c-0.006-0.112-0.017-0.277-0.041-0.483
c-0.005-0.046-0.011-0.094-0.018-0.143c-0.052-0.398-0.147-0.917-0.317-1.482c-0.382-1.276-1.136-2.762-2.603-3.738
c-0.981-0.652-2.295-1.102-4.124-1.104h-36.3v-0.605v-0.605h36.3c0.003,0,0.007,0,0.011,0c2.023,0,3.598,0.515,4.784,1.307
c1.19,0.793,1.978,1.85,2.496,2.885c1.032,2.074,1.024,4.077,1.028,4.127v87.347c0.002,2.028-0.513,3.607-1.307,4.795
c-0.793,1.19-1.849,1.979-2.885,2.496c-2.074,1.032-4.077,1.024-4.127,1.028h-36.3C-20.502,205.197-20.505,205.197-20.508,205.197"
/>
<path fill="#6BC9C7" d="M215.455,141.232h-50.483c-0.01-0.111-0.016-0.204-0.02-0.275l-0.005-0.125v-0.034v-0.776h50.517v0.776
C215.464,140.946,215.461,141.09,215.455,141.232"/>
<path fill="#6BC9C7" d="M215.464,53.875h-50.517v-0.424c0-0.274,0.01-0.535,0.03-0.786H215.4c0.006,0.05,0.012,0.097,0.018,0.143
c0.023,0.206,0.035,0.372,0.041,0.483l0.005,0.125v0.035V53.875"/>
<path fill="#6BC9C7" d="M212.89,133.917h-45.369V61.37v-0.605h45.369V133.917 M168.731,61.975v70.732h42.949V61.975H168.731
M168.126,61.37v0.605V61.37"/>
<path fill="#6BC9C7" d="M172.046,149.116c-2.023,0-3.599-0.514-4.785-1.307c-1.19-0.792-1.979-1.849-2.496-2.884
c-1.032-2.074-1.025-4.077-1.028-4.127V53.451c-0.002-2.028,0.513-3.607,1.307-4.795c0.793-1.19,1.849-1.979,2.884-2.496
c2.075-1.032,4.077-1.025,4.128-1.028v0.605v0.605h-0.035l-0.125,0.005c-0.111,0.006-0.277,0.018-0.483,0.042
c-0.412,0.047-0.989,0.143-1.624,0.334c-1.276,0.383-2.762,1.136-3.738,2.604c-0.555,0.834-0.963,1.91-1.074,3.338
c-0.02,0.251-0.03,0.512-0.03,0.786v0.424v86.147v0.776v0.034l0.005,0.125c0.004,0.071,0.01,0.164,0.02,0.275
c0.006,0.063,0.013,0.133,0.022,0.208c0.047,0.413,0.143,0.989,0.334,1.624c0.383,1.276,1.136,2.762,2.604,3.739
c0.981,0.652,2.295,1.102,4.124,1.103h36.3h0.034l0.125-0.005c0.111-0.006,0.277-0.018,0.483-0.042
c0.413-0.047,0.989-0.143,1.625-0.334c1.275-0.383,2.762-1.136,3.738-2.604c0.599-0.901,1.027-2.084,1.094-3.689
c0.006-0.142,0.009-0.286,0.009-0.434v-0.776V53.875v-0.424v-0.035l-0.005-0.125c-0.006-0.111-0.018-0.277-0.041-0.483
c-0.006-0.046-0.012-0.093-0.018-0.143c-0.053-0.398-0.147-0.916-0.317-1.481c-0.383-1.276-1.136-2.762-2.604-3.738
c-0.981-0.653-2.295-1.102-4.123-1.104h-36.3v-0.605v-0.605h36.3c0.003,0,0.007,0,0.01,0c2.023,0,3.598,0.514,4.785,1.307
c1.189,0.793,1.978,1.849,2.495,2.884c1.032,2.075,1.025,4.077,1.028,4.128v87.347c0.002,2.028-0.512,3.606-1.306,4.794
c-0.794,1.19-1.85,1.979-2.885,2.496c-2.074,1.032-4.077,1.025-4.127,1.028h-36.3C172.052,149.116,172.049,149.116,172.046,149.116
"/>
<path fill="#A59368" d="M127.531,147.617H61.214h-0.606v-44.381h66.923V147.617 M61.819,146.407h64.502v-41.961H61.819V146.407"/>
<path fill="#A59368" d="M53.444,151.116c-2.023,0-3.598-0.514-4.785-1.307c-1.189-0.793-1.978-1.849-2.495-2.884
c-1.032-2.074-1.025-4.077-1.028-4.128l0,0l0,0v-34.741c-0.002-2.028,0.512-3.607,1.307-4.795c0.792-1.19,1.849-1.979,2.884-2.496
c2.074-1.032,4.077-1.025,4.127-1.028h81.848c0.004,0,0.007,0,0.011,0c2.023,0,3.598,0.514,4.784,1.307
c1.19,0.793,1.979,1.849,2.496,2.884c1.031,2.075,1.024,4.077,1.028,4.128v34.741c0.001,2.029-0.513,3.607-1.307,4.796
c-0.793,1.189-1.85,1.978-2.885,2.495c-2.074,1.032-4.077,1.025-4.127,1.028H53.454C53.451,151.116,53.447,151.116,53.444,151.116
M46.346,142.797v0.035l0.005,0.125c0.006,0.111,0.018,0.277,0.042,0.483c0.047,0.413,0.143,0.989,0.334,1.624
c0.383,1.276,1.136,2.763,2.603,3.739c0.982,0.652,2.296,1.101,4.124,1.103h81.848h0.034l0.125-0.005
c0.112-0.006,0.277-0.018,0.483-0.042c0.413-0.047,0.989-0.143,1.625-0.334c1.276-0.383,2.762-1.136,3.738-2.604
c0.652-0.981,1.102-2.295,1.104-4.124v-34.741l-0.001-0.035l-0.005-0.125c-0.006-0.111-0.017-0.276-0.041-0.483
c-0.048-0.412-0.144-0.989-0.335-1.624c-0.383-1.276-1.136-2.762-2.603-3.738c-0.981-0.652-2.295-1.102-4.124-1.104H53.454
l-0.034,0.001l-0.125,0.005c-0.111,0.005-0.277,0.017-0.483,0.041c-0.413,0.048-0.989,0.144-1.624,0.334
c-1.277,0.383-2.762,1.137-3.739,2.604c-0.652,0.981-1.102,2.295-1.103,4.124V142.797"/>
<path fill="#A59368" d="M134.921,130.832c-2.986,0-5.406-2.42-5.406-5.405c0-2.986,2.42-5.406,5.406-5.406
c2.985,0,5.405,2.42,5.405,5.406l0,0l0,0l0,0C140.326,128.412,137.906,130.832,134.921,130.832 M134.921,121.231
c-1.161,0-2.206,0.469-2.967,1.229c-0.76,0.761-1.229,1.806-1.229,2.967c0,1.16,0.469,2.205,1.229,2.966
c0.761,0.761,1.806,1.229,2.967,1.229c1.16,0,2.205-0.468,2.966-1.229c0.761-0.761,1.229-1.806,1.229-2.966
c0-1.161-0.468-2.206-1.229-2.967C137.126,121.7,136.081,121.231,134.921,121.231"/>
<polyline fill="#A59368" points="54.014,132.414 52.804,132.414 52.804,118.44 54.014,118.44 54.014,132.414 "/>
<path fill="#6BC9C7" d="M382.617,300.071H316.3h-0.605V255.69h66.922V300.071 M316.905,298.861h64.502V256.9h-64.502V298.861"/>
<path fill="#6BC9C7" d="M308.532,303.57c-2.024,0-3.6-0.514-4.786-1.307c-1.19-0.793-1.979-1.849-2.496-2.884
c-1.031-2.075-1.024-4.077-1.028-4.128l0,0l0,0V260.51c-0.001-2.028,0.513-3.607,1.307-4.795c0.793-1.19,1.85-1.979,2.885-2.496
c2.074-1.032,4.077-1.025,4.127-1.028h81.847c0.003,0,0.007,0,0.01,0c2.023,0,3.599,0.514,4.786,1.307
c1.189,0.792,1.978,1.849,2.495,2.884c1.032,2.075,1.025,4.077,1.028,4.128v34.741c0.002,2.028-0.512,3.607-1.307,4.795
c-0.793,1.19-1.849,1.979-2.884,2.496c-2.074,1.032-4.077,1.025-4.128,1.028h-81.847C308.538,303.57,308.535,303.57,308.532,303.57
M301.432,295.251l0.001,0.035l0.005,0.125c0.006,0.111,0.017,0.276,0.041,0.483c0.048,0.412,0.144,0.989,0.335,1.624
c0.382,1.276,1.136,2.762,2.603,3.738c0.981,0.653,2.295,1.102,4.124,1.104h81.847l0.035-0.001l0.125-0.005
c0.111-0.005,0.277-0.017,0.483-0.041c0.413-0.047,0.989-0.144,1.624-0.334c1.276-0.383,2.762-1.137,3.739-2.604
c0.652-0.981,1.101-2.295,1.103-4.124V260.51v-0.035l-0.005-0.125c-0.006-0.111-0.018-0.277-0.042-0.483
c-0.047-0.412-0.143-0.989-0.334-1.624c-0.383-1.276-1.136-2.762-2.603-3.738c-0.982-0.653-2.296-1.102-4.125-1.104h-81.847h-0.034
l-0.125,0.005c-0.112,0.006-0.277,0.018-0.483,0.042c-0.413,0.047-0.989,0.143-1.625,0.334c-1.276,0.383-2.762,1.136-3.738,2.604
c-0.652,0.981-1.102,2.295-1.104,4.124V295.251"/>
<polyline fill="#6BC9C7" points="309.101,284.868 307.891,284.868 307.891,270.893 309.101,270.893 309.101,284.868 "/>
<path fill="#A59368" d="M317.712,47.88h-66.317h-0.605V3.499h66.922V47.88 M252,46.67h64.502V4.709H252V46.67"/>
<path fill="#A59368" d="M243.625,51.379c-2.022,0-3.598-0.514-4.784-1.307c-1.19-0.793-1.979-1.849-2.496-2.884
c-1.031-2.075-1.024-4.077-1.028-4.128l0,0l0,0V8.319c-0.001-2.028,0.513-3.607,1.307-4.795c0.793-1.19,1.85-1.979,2.885-2.496
c2.074-1.032,4.077-1.025,4.127-1.028h81.848c0.003,0,0.007,0,0.01,0c2.023,0,3.598,0.514,4.785,1.307
c1.189,0.793,1.978,1.849,2.495,2.885c1.032,2.074,1.025,4.077,1.028,4.127V43.06c0.002,2.028-0.512,3.607-1.307,4.795
c-0.793,1.19-1.849,1.979-2.884,2.496c-2.074,1.032-4.077,1.025-4.127,1.028h-81.848C243.632,51.379,243.629,51.379,243.625,51.379
M236.527,43.06l0.001,0.035l0.005,0.125c0.006,0.111,0.017,0.276,0.041,0.483c0.048,0.412,0.144,0.989,0.335,1.624
c0.383,1.276,1.136,2.762,2.603,3.739c0.981,0.652,2.295,1.101,4.124,1.103h81.848l0.034-0.001l0.125-0.005
c0.111-0.005,0.277-0.017,0.483-0.041c0.413-0.047,0.989-0.144,1.624-0.334c1.277-0.383,2.762-1.137,3.739-2.604
c0.652-0.981,1.102-2.295,1.103-4.124V8.319V8.284l-0.005-0.125c-0.006-0.111-0.018-0.277-0.042-0.483
c-0.047-0.413-0.143-0.989-0.334-1.624c-0.383-1.276-1.136-2.762-2.603-3.738c-0.982-0.652-2.296-1.102-4.124-1.104h-81.848
l-0.034,0l-0.125,0.005c-0.112,0.006-0.277,0.018-0.483,0.041c-0.413,0.048-0.989,0.144-1.625,0.334
c-1.276,0.383-2.762,1.136-3.738,2.604c-0.652,0.981-1.102,2.295-1.104,4.124V43.06"/>
<path fill="#A59368" d="M325.102,31.095c-2.985,0-5.405-2.42-5.405-5.405c0-2.986,2.42-5.406,5.405-5.406
c2.986,0,5.406,2.42,5.406,5.406l0,0l0,0l0,0C330.508,28.675,328.088,31.095,325.102,31.095 M325.102,21.494
c-1.16,0-2.205,0.469-2.966,1.229c-0.761,0.761-1.229,1.806-1.229,2.967c0,1.16,0.468,2.205,1.229,2.966
c0.761,0.761,1.806,1.229,2.966,1.229c1.161,0,2.206-0.468,2.967-1.229c0.761-0.761,1.229-1.806,1.229-2.966
c0-1.161-0.468-2.206-1.229-2.967C327.308,21.963,326.263,21.494,325.102,21.494"/>
<polyline fill="#A59368" points="244.196,32.677 242.986,32.677 242.986,18.702 244.196,18.702 244.196,32.677 "/>
<path fill="#6BC9C7" d="M353.823,147.906c-1.456,0-2.607-0.372-3.474-0.952c-0.871-0.58-1.447-1.353-1.822-2.105
c-0.748-1.507-0.741-2.942-0.744-2.993V45.843c-0.002-1.461,0.37-2.614,0.952-3.484c0.58-0.87,1.353-1.446,2.104-1.822
c1.508-0.748,2.943-0.741,2.993-0.744v0.605v0.605h-0.02l-0.083,0.003c-0.075,0.004-0.188,0.012-0.33,0.029
c-0.283,0.032-0.679,0.098-1.116,0.229c-0.877,0.264-1.884,0.778-2.541,1.766c-0.44,0.663-0.748,1.551-0.75,2.813v96.013
l0.001,0.02l0.003,0.084c0.004,0.075,0.012,0.188,0.028,0.329c0.033,0.283,0.099,0.68,0.23,1.116
c0.263,0.877,0.777,1.885,1.766,2.542c0.662,0.44,1.551,0.748,2.812,0.749h43.197h0.02l0.084-0.004
c0.075-0.003,0.188-0.011,0.33-0.028c0.283-0.032,0.679-0.098,1.116-0.229c0.877-0.264,1.884-0.778,2.541-1.766
c0.44-0.663,0.748-1.551,0.749-2.813V45.843v-0.02l-0.003-0.084c-0.004-0.075-0.012-0.188-0.028-0.33
c-0.033-0.282-0.099-0.679-0.23-1.115c-0.264-0.877-0.778-1.885-1.766-2.542c-0.662-0.44-1.551-0.748-2.813-0.749h-43.197v-0.605
v-0.605h43.197c0.004,0,0.007,0,0.011,0c1.456,0,2.606,0.372,3.473,0.952c0.87,0.58,1.447,1.353,1.822,2.105
c0.748,1.507,0.741,2.942,0.744,2.993v96.013c0.002,1.461-0.371,2.614-0.952,3.484c-0.58,0.87-1.353,1.446-2.104,1.822
c-1.508,0.748-2.943,0.741-2.994,0.744h-43.197C353.829,147.906,353.826,147.906,353.823,147.906"/>
<path fill="#6BC9C7" d="M357.988,139.013c-1.456,0-2.606-0.373-3.473-0.953c-0.871-0.58-1.447-1.353-1.822-2.104
c-0.748-1.507-0.741-2.943-0.744-2.993V60c-0.002-1.461,0.37-2.614,0.952-3.484c0.58-0.87,1.353-1.447,2.105-1.822
c1.507-0.748,2.942-0.741,2.993-0.744v0.605v0.605h-0.02l-0.084,0.003c-0.075,0.004-0.188,0.012-0.33,0.029
c-0.282,0.032-0.679,0.099-1.115,0.229c-0.878,0.264-1.885,0.778-2.542,1.766c-0.44,0.662-0.748,1.551-0.749,2.813v72.963v0.02
l0.003,0.083c0.004,0.075,0.012,0.189,0.029,0.33c0.032,0.283,0.098,0.68,0.229,1.116c0.263,0.877,0.778,1.885,1.766,2.542
c0.662,0.439,1.551,0.747,2.813,0.749h34.864l0.02-0.001l0.084-0.003c0.075-0.004,0.188-0.012,0.329-0.028
c0.283-0.033,0.68-0.099,1.116-0.23c0.877-0.263,1.885-0.777,2.542-1.766c0.439-0.662,0.747-1.551,0.749-2.812V60v-0.02
l-0.004-0.084c-0.004-0.075-0.012-0.188-0.028-0.329c-0.033-0.283-0.099-0.68-0.229-1.116c-0.264-0.878-0.778-1.885-1.766-2.542
c-0.663-0.44-1.551-0.747-2.813-0.749h-34.864v-0.605V53.95h34.864c0.004,0,0.007,0,0.011,0c1.456,0,2.605,0.372,3.473,0.952
c0.87,0.58,1.446,1.353,1.822,2.105c0.748,1.507,0.741,2.942,0.744,2.993v72.963c0.002,1.461-0.371,2.614-0.952,3.483
c-0.581,0.871-1.353,1.447-2.105,1.822c-1.507,0.749-2.943,0.742-2.993,0.745h-34.864
C357.995,139.013,357.991,139.013,357.988,139.013"/>
<path fill="#A59368" d="M-18.909,330.062c-2.974,0-5.263-0.752-6.984-1.902c-1.725-1.149-2.87-2.681-3.625-4.192
c-1.508-3.026-1.501-5.98-1.504-6.03l0,0l0,0v-24.026c0-0.832,0.058-1.611,0.168-2.339c0.155,0.983,0.457,2.277,1.042,3.625v22.74
l0.001,0.058l0.008,0.195c0.009,0.172,0.027,0.425,0.063,0.741c0.073,0.629,0.219,1.507,0.51,2.477
c0.584,1.944,1.738,4.233,4.008,5.745c1.517,1.009,3.544,1.696,6.324,1.698h73.886l0.059-0.001l0.195-0.008
c0.172-0.009,0.425-0.027,0.74-0.063c0.63-0.073,1.507-0.219,2.477-0.51c1.945-0.584,4.234-1.738,5.745-4.008
c1.009-1.517,1.697-3.544,1.698-6.324v-22.352c0.483-0.994,0.846-2.138,1.043-3.448c0.167,1.053,0.166,1.75,0.167,1.774v24.026
c0.002,2.979-0.75,5.271-1.901,6.995c-1.15,1.725-2.682,2.87-4.193,3.625c-3.025,1.508-5.979,1.501-6.03,1.504h-73.886
C-18.902,330.062-18.905,330.062-18.909,330.062"/>
<path fill="#00B6B2" d="M54.988,300.713h-73.886c-2.78-0.002-4.807-0.69-6.324-1.699c-2.27-1.511-3.424-3.8-4.008-5.745
c-0.291-0.969-0.437-1.847-0.51-2.477c-0.036-0.315-0.054-0.568-0.063-0.74l-0.008-0.195l-0.001-0.059v-24.025
c0.002-2.78,0.689-4.808,1.698-6.324c1.512-2.27,3.8-3.424,5.745-4.008c0.97-0.291,1.847-0.437,2.478-0.51
c0.314-0.036,0.568-0.054,0.74-0.063l0.194-0.008l0.059-0.001h73.886c2.78,0.002,4.808,0.689,6.324,1.698
c2.27,1.512,3.425,3.8,4.009,5.745c0.291,0.97,0.437,1.847,0.509,2.477c0.037,0.315,0.055,0.569,0.064,0.741l0.007,0.194
l0.001,0.059v24.025c-0.001,2.781-0.689,4.808-1.698,6.324c-1.511,2.27-3.8,3.425-5.745,4.009c-0.97,0.291-1.847,0.437-2.477,0.51
c-0.315,0.036-0.568,0.054-0.74,0.063l-0.195,0.008L54.988,300.713 M-6.309,257.187c-0.051,0.003-1.873-0.004-3.768,0.938
c-0.945,0.472-1.911,1.194-2.637,2.282c-0.726,1.087-1.196,2.531-1.194,4.379v25.012c0.003,0.051-0.004,1.874,0.938,3.768
c0.472,0.945,1.193,1.911,2.282,2.637c1.085,0.725,2.525,1.194,4.368,1.194c0.004,0,0.007,0,0.011,0h43.772
c0.05-0.003,1.873,0.004,3.767-0.938c0.946-0.472,1.912-1.193,2.637-2.282c0.727-1.087,1.196-2.531,1.195-4.379v-25.012
c-0.003-0.051,0.004-1.873-0.938-3.768c-0.472-0.945-1.194-1.911-2.282-2.637c-1.086-0.725-2.526-1.194-4.37-1.194
c-0.003,0-0.006,0-0.009,0H-6.309v0.605v0.605h43.772c1.649,0.002,2.828,0.407,3.708,0.991c1.315,0.875,1.992,2.209,2.337,3.359
c0.172,0.572,0.259,1.091,0.302,1.463c0.021,0.185,0.031,0.334,0.037,0.434l0.004,0.112l0.001,0.03v25.012
c-0.002,1.649-0.407,2.828-0.991,3.708c-0.875,1.316-2.21,1.993-3.359,2.338c-0.572,0.172-1.091,0.258-1.463,0.301
c-0.186,0.022-0.334,0.032-0.435,0.037l-0.111,0.005h-0.03H-6.309c-1.649-0.002-2.828-0.406-3.708-0.991
c-1.315-0.875-1.993-2.209-2.338-3.359c-0.171-0.572-0.258-1.091-0.301-1.462c-0.021-0.186-0.032-0.335-0.037-0.435l-0.004-0.112
l-0.001-0.03v-25.012c0.002-1.649,0.406-2.828,0.991-3.708c0.875-1.315,2.209-1.993,3.359-2.338
c0.572-0.171,1.091-0.258,1.463-0.301c0.185-0.021,0.334-0.032,0.434-0.037l0.112-0.004l0.03-0.001v-0.605V257.187 M56.223,281.518
L56.223,281.518c2.151-0.001,3.895-1.745,3.896-3.897c-0.001-2.152-1.745-3.896-3.896-3.896c-2.152,0-3.896,1.744-3.897,3.896
C52.327,279.773,54.071,281.517,56.223,281.518 M56.223,281.518v-0.605v-0.605c-1.484-0.003-2.684-1.203-2.687-2.687
c0.003-1.483,1.203-2.683,2.687-2.686c1.483,0.003,2.683,1.203,2.686,2.686c-0.003,1.484-1.203,2.684-2.686,2.687v0.605V281.518
L56.223,281.518"/>
<path fill="#A59368" d="M-18.909,301.923c-2.974,0-5.263-0.752-6.984-1.902c-1.725-1.149-2.87-2.682-3.625-4.192
c-0.105-0.211-0.203-0.422-0.294-0.631c-0.585-1.348-0.887-2.642-1.042-3.625c-0.167-1.054-0.166-1.75-0.168-1.775l0,0l0,0v-24.025
c-0.002-2.979,0.751-5.272,1.902-6.995c1.149-1.725,2.681-2.87,4.192-3.625c3.026-1.508,5.98-1.501,6.03-1.504h73.886
c0.004,0,0.008,0,0.011,0c2.974,0,5.263,0.752,6.984,1.902c1.725,1.149,2.871,2.681,3.626,4.192c1.507,3.026,1.5,5.98,1.503,6.03
v24.025c0.001,0.833-0.058,1.612-0.167,2.34c-0.197,1.31-0.56,2.454-1.043,3.448c-0.209,0.43-0.44,0.832-0.691,1.208
c-1.15,1.724-2.682,2.87-4.193,3.625c-3.025,1.507-5.979,1.5-6.03,1.504h-73.886C-18.902,301.923-18.905,301.923-18.909,301.923
M-29.812,289.798l0.001,0.059l0.008,0.195c0.009,0.172,0.027,0.425,0.063,0.74c0.073,0.63,0.219,1.508,0.51,2.477
c0.584,1.945,1.738,4.234,4.008,5.745c1.517,1.009,3.544,1.697,6.324,1.699h73.886l0.059-0.001l0.195-0.008
c0.172-0.009,0.425-0.027,0.74-0.063c0.63-0.073,1.507-0.219,2.477-0.51c1.945-0.584,4.234-1.739,5.745-4.009
c1.009-1.516,1.697-3.543,1.698-6.324v-24.025l-0.001-0.059l-0.007-0.194c-0.009-0.172-0.027-0.426-0.064-0.741
c-0.072-0.63-0.218-1.507-0.509-2.477c-0.584-1.945-1.739-4.233-4.009-5.745c-1.516-1.009-3.544-1.696-6.324-1.698h-73.886
l-0.059,0.001l-0.194,0.008c-0.172,0.009-0.426,0.027-0.74,0.063c-0.631,0.073-1.508,0.219-2.478,0.51
c-1.945,0.584-4.233,1.738-5.745,4.008c-1.009,1.516-1.696,3.544-1.698,6.324V289.798"/>
<path fill="#A59368" d="M-6.32,297.397c-1.843,0-3.283-0.469-4.368-1.194c-1.089-0.726-1.81-1.692-2.282-2.637
c-0.942-1.894-0.935-3.717-0.938-3.768v-25.012c-0.002-1.848,0.468-3.292,1.194-4.379c0.726-1.088,1.692-1.81,2.637-2.282
c1.895-0.942,3.717-0.935,3.768-0.938v0.605v0.605l-0.03,0.001l-0.112,0.004c-0.1,0.005-0.249,0.016-0.434,0.037
c-0.372,0.043-0.891,0.13-1.463,0.301c-1.15,0.345-2.484,1.023-3.359,2.338c-0.585,0.88-0.989,2.059-0.991,3.708v25.012l0.001,0.03
l0.004,0.112c0.005,0.1,0.016,0.249,0.037,0.435c0.043,0.371,0.13,0.89,0.301,1.462c0.345,1.15,1.023,2.484,2.338,3.359
c0.88,0.585,2.059,0.989,3.708,0.991h43.772h0.03l0.111-0.005c0.101-0.005,0.249-0.015,0.435-0.037
c0.372-0.043,0.891-0.129,1.463-0.301c1.149-0.345,2.484-1.022,3.359-2.338c0.584-0.88,0.989-2.059,0.991-3.708v-25.012
l-0.001-0.03l-0.004-0.112c-0.006-0.1-0.016-0.249-0.037-0.434c-0.043-0.372-0.13-0.891-0.302-1.463
c-0.345-1.15-1.022-2.484-2.337-3.359c-0.88-0.584-2.059-0.989-3.708-0.991H-6.309v-0.605v-0.605h43.772c0.003,0,0.006,0,0.009,0
c1.844,0,3.284,0.469,4.37,1.194c1.088,0.726,1.81,1.692,2.282,2.637c0.942,1.895,0.935,3.717,0.938,3.768v25.012
c0.001,1.848-0.468,3.292-1.195,4.379c-0.725,1.089-1.691,1.81-2.637,2.282c-1.894,0.942-3.717,0.935-3.767,0.938H-6.309
C-6.313,297.397-6.316,297.397-6.32,297.397"/>
<path fill="#A59368" d="M56.223,281.518L56.223,281.518L56.223,281.518L56.223,281.518 M56.223,281.518
c-2.152-0.001-3.896-1.745-3.897-3.897c0.001-2.152,1.745-3.896,3.897-3.896c2.151,0,3.895,1.744,3.896,3.896
C60.118,279.773,58.374,281.517,56.223,281.518v-0.605v-0.605c1.483-0.003,2.683-1.203,2.686-2.687
c-0.003-1.483-1.203-2.683-2.686-2.686c-1.484,0.003-2.684,1.203-2.687,2.686c0.003,1.484,1.203,2.684,2.687,2.687v0.605V281.518
L56.223,281.518"/>
<polyline fill="#A59368" points="61.056,307.188 55.429,307.188 55.429,306.666 54.219,306.666 54.219,307.188 49.258,307.188
49.258,306.666 48.048,306.666 48.048,307.188 43.087,307.188 43.087,306.666 41.877,306.666 41.877,307.188 36.916,307.188
36.916,306.666 35.706,306.666 35.706,307.188 30.745,307.188 30.745,306.666 29.535,306.666 29.535,307.188 24.574,307.188
24.574,306.666 23.364,306.666 23.364,307.188 18.403,307.188 18.403,306.666 17.193,306.666 17.193,307.188 12.233,307.188
12.233,306.666 11.023,306.666 11.023,307.188 6.062,307.188 6.062,306.666 4.852,306.666 4.852,307.188 -0.109,307.188
-0.109,306.666 -1.319,306.666 -1.319,307.188 -6.28,307.188 -6.28,306.666 -7.49,306.666 -7.49,307.188 -12.451,307.188
-12.451,306.666 -13.661,306.666 -13.661,307.188 -18.622,307.188 -18.622,306.666 -19.832,306.666 -19.832,307.188
-24.966,307.188 -24.966,306.633 -25.645,306.633 -25.645,305.978 61.406,305.978 61.406,306.428 61.056,306.428 61.056,307.188
"/>
<path fill="#A59368" d="M61.056,312.866h-5.627v-1.21h5.627V312.866 M54.219,312.866h-4.961v-1.21h4.961V312.866 M48.048,312.866
h-4.961v-1.21h4.961V312.866 M41.877,312.866h-4.961v-1.21h4.961V312.866 M35.706,312.866h-4.961v-1.21h4.961V312.866
M29.535,312.866h-4.961v-1.21h4.961V312.866 M23.364,312.866h-4.961v-1.21h4.961V312.866 M17.193,312.866h-4.96v-1.21h4.96
V312.866 M11.023,312.866H6.062v-1.21h4.961V312.866 M4.852,312.866h-4.961v-1.21h4.961V312.866 M-1.319,312.866H-6.28v-1.21h4.961
V312.866 M-7.49,312.866h-4.961v-1.21h4.961V312.866 M-13.661,312.866h-4.961v-1.21h4.961V312.866 M-19.832,312.866h-5.134v-1.21
h5.134V312.866"/>
<path fill="#A59368" d="M-16.859,324.006c-2.127,0-3.809-0.523-5.104-1.324c-1.298-0.802-2.2-1.87-2.82-2.923
c-1.238-2.11-1.385-4.161-1.391-4.212l-0.002-0.022v-8.892h0.531h0.679v0.555v4.468v1.21v2.608l0.002,0.019l0.015,0.128
c0.014,0.115,0.039,0.284,0.08,0.496c0.079,0.412,0.219,0.985,0.458,1.619v1.054h0.473c0.546,1.037,1.371,2.097,2.611,2.862
c0.441,0.272,0.936,0.509,1.495,0.696v1.103h1.21v-0.801c0.54,0.094,1.129,0.146,1.773,0.146h3.188v0.655h1.21v-0.655h4.961v0.655
h1.21v-0.655h4.961v0.655h1.21v-0.655h4.961v0.655h1.21v-0.655h4.961v0.655h1.21v-0.655h4.96v0.655h1.21v-0.655h4.961v0.655h1.21
v-0.655h4.961v0.655h1.21v-0.655h4.961v0.655h1.21v-0.655h4.961v0.655h1.21v-0.655h4.961v0.655h1.21v-0.655h3.662l0.031-0.002
l0.144-0.013c0.128-0.012,0.318-0.035,0.554-0.073c0.168-0.027,0.36-0.062,0.57-0.106v0.849h1.21v-1.175
c0.026-0.008,0.052-0.017,0.078-0.026c1.459-0.489,3.171-1.4,4.291-3.055c0.088-0.13,0.172-0.265,0.253-0.405h0.532v-1.153
c0.296-0.831,0.472-1.805,0.473-2.957v-1.814v-1.21v-4.468v-0.76h0.35h0.86v8.252c0.002,2.174-0.579,3.889-1.467,5.194
c-0.886,1.307-2.062,2.199-3.217,2.806c-2.314,1.211-4.564,1.32-4.612,1.325l-0.015,0.001h-69.804
C-16.852,324.006-16.855,324.006-16.859,324.006"/>
<path fill="#A59368" d="M60.583,318.79h-0.532h-4.622v-1.21h5.154v0.057V318.79 M54.219,318.79h-4.961v-1.21h4.961V318.79
M48.048,318.79h-4.961v-1.21h4.961V318.79 M41.877,318.79h-4.961v-1.21h4.961V318.79 M35.706,318.79h-4.961v-1.21h4.961V318.79
M29.535,318.79h-4.961v-1.21h4.961V318.79 M23.364,318.79h-4.961v-1.21h4.961V318.79 M17.193,318.79h-4.96v-1.21h4.96V318.79
M11.023,318.79H6.062v-1.21h4.961V318.79 M4.852,318.79h-4.961v-1.21h4.961V318.79 M-1.319,318.79H-6.28v-1.21h4.961V318.79
M-7.49,318.79h-4.961v-1.21h4.961V318.79 M-13.661,318.79h-4.961v-1.21h4.961V318.79 M-19.832,318.79h-4.106h-0.473v-1.054v-0.156
h4.579V318.79"/>
<polyline fill="#A59368" points="6.062,323.451 4.852,323.451 4.852,322.796 4.852,318.79 4.852,317.58 4.852,312.866
4.852,311.656 4.852,307.188 4.852,306.666 6.062,306.666 6.062,307.188 6.062,311.656 6.062,312.866 6.062,317.58 6.062,318.79
6.062,322.796 6.062,323.451 "/>
<polyline fill="#A59368" points="12.233,323.451 11.023,323.451 11.023,322.796 11.023,318.79 11.023,317.58 11.023,312.866
11.023,311.656 11.023,307.188 11.023,306.666 12.233,306.666 12.233,307.188 12.233,311.656 12.233,312.866 12.233,317.58
12.233,318.79 12.233,322.796 12.233,323.451 "/>
<polyline fill="#A59368" points="18.403,323.451 17.193,323.451 17.193,322.796 17.193,318.79 17.193,317.58 17.193,312.866
17.193,311.656 17.193,307.188 17.193,306.666 18.403,306.666 18.403,307.188 18.403,311.656 18.403,312.866 18.403,317.58
18.403,318.79 18.403,322.796 18.403,323.451 "/>
<polyline fill="#A59368" points="24.574,323.451 23.364,323.451 23.364,322.796 23.364,318.79 23.364,317.58 23.364,312.866
23.364,311.656 23.364,307.188 23.364,306.666 24.574,306.666 24.574,307.188 24.574,311.656 24.574,312.866 24.574,317.58
24.574,318.79 24.574,322.796 24.574,323.451 "/>
<polyline fill="#A59368" points="30.745,323.451 29.535,323.451 29.535,322.796 29.535,318.79 29.535,317.58 29.535,312.866
29.535,311.656 29.535,307.188 29.535,306.666 30.745,306.666 30.745,307.188 30.745,311.656 30.745,312.866 30.745,317.58
30.745,318.79 30.745,322.796 30.745,323.451 "/>
<polyline fill="#A59368" points="36.916,323.451 35.706,323.451 35.706,322.796 35.706,318.79 35.706,317.58 35.706,312.866
35.706,311.656 35.706,307.188 35.706,306.666 36.916,306.666 36.916,307.188 36.916,311.656 36.916,312.866 36.916,317.58
36.916,318.79 36.916,322.796 36.916,323.451 "/>
<polyline fill="#A59368" points="43.087,323.451 41.877,323.451 41.877,322.796 41.877,318.79 41.877,317.58 41.877,312.866
41.877,311.656 41.877,307.188 41.877,306.666 43.087,306.666 43.087,307.188 43.087,311.656 43.087,312.866 43.087,317.58
43.087,318.79 43.087,322.796 43.087,323.451 "/>
<polyline fill="#A59368" points="49.258,323.451 48.048,323.451 48.048,322.796 48.048,318.79 48.048,317.58 48.048,312.866
48.048,311.656 48.048,307.188 48.048,306.666 49.258,306.666 49.258,307.188 49.258,311.656 49.258,312.866 49.258,317.58
49.258,318.79 49.258,322.796 49.258,323.451 "/>
<polyline fill="#A59368" points="55.429,323.451 54.219,323.451 54.219,322.602 54.219,318.79 54.219,317.58 54.219,312.866
54.219,311.656 54.219,307.188 54.219,306.666 55.429,306.666 55.429,307.188 55.429,311.656 55.429,312.866 55.429,317.58
55.429,318.79 55.429,322.276 55.429,323.451 "/>
<path fill="#0095A8" d="M248.904,150.377c-2.974,0-5.263-0.751-6.984-1.901c-1.725-1.15-2.871-2.682-3.626-4.193
c-1.507-3.025-1.5-5.979-1.503-6.03l0,0l0,0v-24.025c-0.001-0.833,0.058-1.612,0.167-2.339c0.156,0.983,0.457,2.277,1.043,3.625
v22.739l0.001,0.059l0.007,0.195c0.009,0.172,0.027,0.425,0.063,0.74c0.073,0.63,0.219,1.507,0.51,2.477
c0.584,1.945,1.739,4.234,4.009,5.745c1.516,1.009,3.544,1.697,6.324,1.698h73.886l0.058-0.001l0.195-0.007
c0.172-0.009,0.426-0.027,0.741-0.063c0.629-0.073,1.507-0.219,2.477-0.51c1.945-0.584,4.233-1.739,5.745-4.009
c1.009-1.516,1.696-3.544,1.698-6.324v-22.352c0.483-0.994,0.845-2.138,1.042-3.448c0.167,1.054,0.166,1.751,0.168,1.775v24.025
c0.002,2.98-0.751,5.272-1.902,6.995c-1.149,1.725-2.681,2.871-4.192,3.626c-3.026,1.507-5.98,1.5-6.03,1.503h-73.886
C248.911,150.377,248.907,150.377,248.904,150.377"/>
<path fill="#00B6B2" d="M322.801,121.028h-73.886c-2.78-0.002-4.808-0.689-6.324-1.698c-2.27-1.512-3.425-3.8-4.009-5.745
c-0.291-0.97-0.437-1.847-0.51-2.477c-0.036-0.315-0.054-0.569-0.063-0.74l-0.007-0.195l-0.001-0.059V86.089
c0.001-2.78,0.689-4.808,1.698-6.324c1.511-2.27,3.8-3.425,5.745-4.008c0.97-0.291,1.847-0.438,2.477-0.51
c0.315-0.037,0.568-0.055,0.74-0.064l0.195-0.007l0.059-0.001h73.886c2.78,0.001,4.807,0.689,6.324,1.698
c2.27,1.511,3.424,3.8,4.008,5.745c0.291,0.97,0.437,1.847,0.51,2.477c0.036,0.315,0.054,0.568,0.063,0.74l0.008,0.195l0.001,0.059
v24.025c-0.002,2.78-0.689,4.808-1.698,6.324c-1.512,2.27-3.8,3.425-5.745,4.008c-0.97,0.291-1.848,0.438-2.477,0.51
c-0.315,0.037-0.569,0.054-0.741,0.063l-0.195,0.008L322.801,121.028 M261.503,77.503c-0.05,0.003-1.873-0.004-3.767,0.938
c-0.945,0.472-1.912,1.193-2.637,2.282c-0.727,1.087-1.196,2.53-1.194,4.378v25.013c0.003,0.05-0.004,1.873,0.938,3.768
c0.472,0.945,1.193,1.911,2.281,2.636c1.086,0.726,2.527,1.195,4.37,1.195c0.003,0,0.006,0,0.009,0h43.772
c0.051-0.004,1.874,0.004,3.768-0.938c0.945-0.472,1.912-1.194,2.637-2.282c0.726-1.087,1.196-2.531,1.194-4.379V85.101
c-0.003-0.05,0.004-1.873-0.938-3.767c-0.472-0.945-1.193-1.912-2.282-2.637c-1.085-0.725-2.526-1.194-4.369-1.194
c-0.003,0-0.006,0-0.01,0H261.503v0.605v0.605h43.772c1.649,0.001,2.828,0.406,3.708,0.991c1.316,0.875,1.993,2.209,2.338,3.358
c0.172,0.572,0.258,1.092,0.301,1.463c0.022,0.186,0.032,0.335,0.037,0.435l0.005,0.112v0.029v25.013
c-0.001,1.649-0.406,2.828-0.991,3.708c-0.875,1.315-2.209,1.993-3.359,2.338c-0.572,0.171-1.091,0.258-1.462,0.301
c-0.186,0.021-0.335,0.032-0.435,0.037l-0.112,0.004l-0.03,0.001h-43.772c-1.648-0.002-2.828-0.407-3.707-0.991
c-1.316-0.875-1.993-2.209-2.338-3.359c-0.172-0.572-0.259-1.091-0.301-1.463c-0.022-0.186-0.032-0.334-0.037-0.434l-0.005-0.112
v-0.03V85.101c0.001-1.648,0.406-2.827,0.991-3.707c0.875-1.316,2.209-1.993,3.358-2.338c0.572-0.172,1.092-0.258,1.463-0.301
c0.186-0.022,0.335-0.032,0.435-0.038l0.112-0.004h0.029v-0.605V77.503 M324.035,101.833L324.035,101.833
c2.152,0,3.896-1.744,3.896-3.896s-1.744-3.896-3.896-3.896s-3.896,1.744-3.896,3.896S321.883,101.833,324.035,101.833
M324.035,101.833v-0.605v-0.605c-1.483-0.003-2.683-1.203-2.686-2.686c0.003-1.483,1.203-2.684,2.686-2.686
c1.483,0.002,2.684,1.203,2.686,2.686c-0.002,1.483-1.203,2.683-2.686,2.686v0.605V101.833L324.035,101.833"/>
<path fill="#0095A8" d="M248.904,122.238c-2.974,0-5.263-0.752-6.984-1.901c-1.725-1.15-2.871-2.682-3.626-4.193
c-0.105-0.211-0.202-0.421-0.293-0.63c-0.586-1.348-0.887-2.642-1.043-3.625c-0.167-1.054-0.166-1.751-0.167-1.775l0,0l0,0V86.089
c-0.002-2.98,0.75-5.272,1.901-6.995c1.15-1.725,2.682-2.871,4.193-3.625c3.025-1.508,5.979-1.501,6.03-1.504h73.886
c0.004,0,0.007,0,0.011,0c2.974,0,5.263,0.752,6.984,1.901c1.725,1.15,2.87,2.682,3.625,4.193c1.508,3.025,1.501,5.979,1.504,6.03
v24.025c0,0.833-0.058,1.612-0.168,2.339c-0.197,1.31-0.559,2.454-1.042,3.448c-0.209,0.431-0.441,0.833-0.692,1.208
c-1.149,1.725-2.681,2.87-4.192,3.625c-3.026,1.508-5.98,1.501-6.03,1.504h-73.886
C248.911,122.238,248.907,122.238,248.904,122.238 M238.001,110.114l0.001,0.059l0.007,0.195c0.009,0.171,0.027,0.425,0.063,0.74
c0.073,0.63,0.219,1.507,0.51,2.477c0.584,1.945,1.739,4.233,4.009,5.745c1.516,1.009,3.544,1.696,6.324,1.698h73.886l0.058-0.001
l0.195-0.008c0.172-0.009,0.426-0.026,0.741-0.063c0.629-0.072,1.507-0.219,2.477-0.51c1.945-0.583,4.233-1.738,5.745-4.008
c1.009-1.516,1.696-3.544,1.698-6.324V86.089l-0.001-0.059l-0.008-0.195c-0.009-0.172-0.027-0.425-0.063-0.74
c-0.073-0.63-0.219-1.507-0.51-2.477c-0.584-1.945-1.738-4.234-4.008-5.745c-1.517-1.009-3.544-1.697-6.324-1.698h-73.886
l-0.059,0.001l-0.195,0.007c-0.172,0.009-0.425,0.027-0.74,0.064c-0.63,0.072-1.507,0.219-2.477,0.51
c-1.945,0.583-4.234,1.738-5.745,4.008c-1.009,1.516-1.697,3.544-1.698,6.324V110.114"/>
<path fill="#0095A8" d="M261.494,117.713c-1.843,0-3.284-0.469-4.37-1.195c-1.088-0.725-1.809-1.691-2.281-2.636
c-0.942-1.895-0.935-3.718-0.938-3.768V85.101c-0.002-1.848,0.467-3.291,1.194-4.378c0.725-1.089,1.692-1.81,2.637-2.282
c1.894-0.942,3.717-0.935,3.767-0.938v0.605v0.605h-0.029l-0.112,0.004c-0.1,0.006-0.249,0.016-0.435,0.038
c-0.371,0.043-0.891,0.129-1.463,0.301c-1.149,0.345-2.483,1.022-3.358,2.338c-0.585,0.88-0.99,2.059-0.991,3.707v25.013v0.03
l0.005,0.112c0.005,0.1,0.015,0.248,0.037,0.434c0.042,0.372,0.129,0.891,0.301,1.463c0.345,1.15,1.022,2.484,2.338,3.359
c0.879,0.584,2.059,0.989,3.707,0.991h43.772l0.03-0.001l0.112-0.004c0.1-0.005,0.249-0.016,0.435-0.037
c0.371-0.043,0.89-0.13,1.462-0.301c1.15-0.345,2.484-1.023,3.359-2.338c0.585-0.88,0.99-2.059,0.991-3.708V85.101v-0.029
l-0.005-0.112c-0.005-0.1-0.015-0.249-0.037-0.435c-0.043-0.371-0.129-0.891-0.301-1.463c-0.345-1.149-1.022-2.483-2.338-3.358
c-0.88-0.585-2.059-0.99-3.708-0.991h-43.772v-0.605v-0.605h43.772c0.004,0,0.007,0,0.01,0c1.843,0,3.284,0.469,4.369,1.194
c1.089,0.725,1.81,1.692,2.282,2.637c0.942,1.894,0.935,3.717,0.938,3.767v25.013c0.002,1.848-0.468,3.292-1.194,4.379
c-0.725,1.088-1.692,1.81-2.637,2.282c-1.894,0.942-3.717,0.934-3.768,0.938h-43.772
C261.5,117.713,261.497,117.713,261.494,117.713"/>
<path fill="#0095A8" d="M324.035,101.833L324.035,101.833L324.035,101.833L324.035,101.833 M324.035,101.833
c-2.152,0-3.896-1.744-3.896-3.896s1.744-3.896,3.896-3.896s3.896,1.744,3.896,3.896S326.187,101.833,324.035,101.833v-0.605
v-0.605c1.483-0.003,2.684-1.203,2.686-2.686c-0.002-1.483-1.203-2.684-2.686-2.686c-1.483,0.002-2.683,1.203-2.686,2.686
c0.003,1.483,1.203,2.683,2.686,2.686v0.605V101.833L324.035,101.833"/>
<polyline fill="#0095A8" points="328.869,127.504 323.241,127.504 323.241,126.981 322.031,126.981 322.031,127.504
317.07,127.504 317.07,126.981 315.86,126.981 315.86,127.504 310.899,127.504 310.899,126.981 309.69,126.981 309.69,127.504
304.729,127.504 304.729,126.981 303.519,126.981 303.519,127.504 298.558,127.504 298.558,126.981 297.348,126.981
297.348,127.504 292.387,127.504 292.387,126.981 291.177,126.981 291.177,127.504 286.216,127.504 286.216,126.981
285.006,126.981 285.006,127.504 280.045,127.504 280.045,126.981 278.835,126.981 278.835,127.504 273.874,127.504
273.874,126.981 272.664,126.981 272.664,127.504 267.703,127.504 267.703,126.981 266.493,126.981 266.493,127.504
261.532,127.504 261.532,126.981 260.322,126.981 260.322,127.504 255.361,127.504 255.361,126.981 254.151,126.981
254.151,127.504 249.191,127.504 249.191,126.981 247.981,126.981 247.981,127.504 242.847,127.504 242.847,126.948
242.168,126.948 242.168,126.294 329.219,126.294 329.219,126.743 328.869,126.743 328.869,127.504 "/>
<path fill="#0095A8" d="M328.869,133.181h-5.628v-1.21h5.628V133.181 M322.031,133.181h-4.961v-1.21h4.961V133.181 M315.86,133.181
h-4.961v-1.21h4.961V133.181 M309.69,133.181h-4.961v-1.21h4.961V133.181 M303.519,133.181h-4.961v-1.21h4.961V133.181
M297.348,133.181h-4.961v-1.21h4.961V133.181 M291.177,133.181h-4.961v-1.21h4.961V133.181 M285.006,133.181h-4.961v-1.21h4.961
V133.181 M278.835,133.181h-4.961v-1.21h4.961V133.181 M272.664,133.181h-4.961v-1.21h4.961V133.181 M266.493,133.181h-4.961v-1.21
h4.961V133.181 M260.322,133.181h-4.961v-1.21h4.961V133.181 M254.151,133.181h-4.96v-1.21h4.96V133.181 M247.981,133.181h-5.134
v-1.21h5.134V133.181"/>
<path fill="#0095A8" d="M250.954,144.322c-2.127,0-3.809-0.524-5.104-1.325c-1.298-0.801-2.2-1.87-2.82-2.923
c-1.238-2.109-1.385-4.16-1.392-4.211l-0.001-0.023v-8.892h0.531h0.679v0.556v4.467v1.21v2.611l0.001,0.016l0.015,0.129
c0.015,0.114,0.04,0.284,0.08,0.495c0.08,0.413,0.22,0.985,0.459,1.619v1.054h0.473c0.546,1.037,1.371,2.098,2.611,2.863
c0.44,0.271,0.935,0.508,1.495,0.695v1.103h1.21v-0.8c0.539,0.094,1.128,0.145,1.772,0.146h3.188v0.654h1.21v-0.654h4.961v0.654
h1.21v-0.654h4.961v0.654h1.21v-0.654h4.961v0.654h1.21v-0.654h4.961v0.654h1.21v-0.654h4.961v0.654h1.21v-0.654h4.961v0.654h1.21
v-0.654h4.961v0.654h1.21v-0.654h4.961v0.654h1.21v-0.654h4.961v0.654h1.209v-0.654h4.961v0.654h1.21v-0.654h3.663l0.03-0.002
l0.145-0.013c0.128-0.013,0.317-0.035,0.553-0.073c0.168-0.027,0.36-0.062,0.57-0.107v0.849h1.21v-1.174
c0.026-0.009,0.052-0.017,0.078-0.026c1.459-0.489,3.172-1.4,4.291-3.056c0.088-0.13,0.173-0.265,0.254-0.405h0.532v-1.153
c0.296-0.831,0.472-1.805,0.473-2.957v-1.814v-1.21v-4.467v-0.761h0.35h0.86v8.252c0.002,2.175-0.58,3.889-1.467,5.194
c-0.887,1.307-2.062,2.2-3.218,2.806c-2.314,1.212-4.563,1.321-4.611,1.326l-0.016,0.001h-69.804
C250.96,144.322,250.957,144.322,250.954,144.322"/>
<path fill="#0095A8" d="M328.396,139.105h-0.532h-4.623v-1.21h5.155v0.057V139.105 M322.031,139.105h-4.961v-1.21h4.961V139.105
M315.86,139.105h-4.961v-1.21h4.961V139.105 M309.69,139.105h-4.961v-1.21h4.961V139.105 M303.519,139.105h-4.961v-1.21h4.961
V139.105 M297.348,139.105h-4.961v-1.21h4.961V139.105 M291.177,139.105h-4.961v-1.21h4.961V139.105 M285.006,139.105h-4.961v-1.21
h4.961V139.105 M278.835,139.105h-4.961v-1.21h4.961V139.105 M272.664,139.105h-4.961v-1.21h4.961V139.105 M266.493,139.105h-4.961
v-1.21h4.961V139.105 M260.322,139.105h-4.961v-1.21h4.961V139.105 M254.151,139.105h-4.96v-1.21h4.96V139.105 M247.981,139.105
h-4.106h-0.473v-1.054v-0.156h4.579V139.105"/>
<polyline fill="#0095A8" points="249.191,143.766 247.981,143.766 247.981,142.663 247.981,139.105 247.981,137.895
247.981,133.181 247.981,131.971 247.981,127.504 247.981,126.981 249.191,126.981 249.191,127.504 249.191,131.971
249.191,133.181 249.191,137.895 249.191,139.105 249.191,142.966 249.191,143.766 "/>
<polyline fill="#0095A8" points="255.361,143.766 254.151,143.766 254.151,143.112 254.151,139.105 254.151,137.895
254.151,133.181 254.151,131.971 254.151,127.504 254.151,126.981 255.361,126.981 255.361,127.504 255.361,131.971
255.361,133.181 255.361,137.895 255.361,139.105 255.361,143.112 255.361,143.766 "/>
<polyline fill="#0095A8" points="261.532,143.766 260.322,143.766 260.322,143.112 260.322,139.105 260.322,137.895
260.322,133.181 260.322,131.971 260.322,127.504 260.322,126.981 261.532,126.981 261.532,127.504 261.532,131.971
261.532,133.181 261.532,137.895 261.532,139.105 261.532,143.112 261.532,143.766 "/>
<polyline fill="#0095A8" points="267.703,143.766 266.493,143.766 266.493,143.112 266.493,139.105 266.493,137.895
266.493,133.181 266.493,131.971 266.493,127.504 266.493,126.981 267.703,126.981 267.703,127.504 267.703,131.971
267.703,133.181 267.703,137.895 267.703,139.105 267.703,143.112 267.703,143.766 "/>
<polyline fill="#0095A8" points="273.874,143.766 272.664,143.766 272.664,143.112 272.664,139.105 272.664,137.895
272.664,133.181 272.664,131.971 272.664,127.504 272.664,126.981 273.874,126.981 273.874,127.504 273.874,131.971
273.874,133.181 273.874,137.895 273.874,139.105 273.874,143.112 273.874,143.766 "/>
<polyline fill="#0095A8" points="280.045,143.766 278.835,143.766 278.835,143.112 278.835,139.105 278.835,137.895
278.835,133.181 278.835,131.971 278.835,127.504 278.835,126.981 280.045,126.981 280.045,127.504 280.045,131.971
280.045,133.181 280.045,137.895 280.045,139.105 280.045,143.112 280.045,143.766 "/>
<polyline fill="#0095A8" points="286.216,143.766 285.006,143.766 285.006,143.112 285.006,139.105 285.006,137.895
285.006,133.181 285.006,131.971 285.006,127.504 285.006,126.981 286.216,126.981 286.216,127.504 286.216,131.971
286.216,133.181 286.216,137.895 286.216,139.105 286.216,143.112 286.216,143.766 "/>
<polyline fill="#0095A8" points="292.387,143.766 291.177,143.766 291.177,143.112 291.177,139.105 291.177,137.895
291.177,133.181 291.177,131.971 291.177,127.504 291.177,126.981 292.387,126.981 292.387,127.504 292.387,131.971
292.387,133.181 292.387,137.895 292.387,139.105 292.387,143.112 292.387,143.766 "/>
<polyline fill="#0095A8" points="298.558,143.766 297.348,143.766 297.348,143.112 297.348,139.105 297.348,137.895
297.348,133.181 297.348,131.971 297.348,127.504 297.348,126.981 298.558,126.981 298.558,127.504 298.558,131.971
298.558,133.181 298.558,137.895 298.558,139.105 298.558,143.112 298.558,143.766 "/>
<polyline fill="#0095A8" points="304.729,143.766 303.519,143.766 303.519,143.112 303.519,139.105 303.519,137.895
303.519,133.181 303.519,131.971 303.519,127.504 303.519,126.981 304.729,126.981 304.729,127.504 304.729,131.971
304.729,133.181 304.729,137.895 304.729,139.105 304.729,143.112 304.729,143.766 "/>
<polyline fill="#0095A8" points="310.899,143.766 309.69,143.766 309.69,143.112 309.69,139.105 309.69,137.895 309.69,133.181
309.69,131.971 309.69,127.504 309.69,126.981 310.899,126.981 310.899,127.504 310.899,131.971 310.899,133.181 310.899,137.895
310.899,139.105 310.899,143.112 310.899,143.766 "/>
<polyline fill="#0095A8" points="317.07,143.766 315.86,143.766 315.86,143.112 315.86,139.105 315.86,137.895 315.86,133.181
315.86,131.971 315.86,127.504 315.86,126.981 317.07,126.981 317.07,127.504 317.07,131.971 317.07,133.181 317.07,137.895
317.07,139.105 317.07,143.112 317.07,143.766 "/>
<polyline fill="#0095A8" points="323.241,143.766 322.031,143.766 322.031,142.917 322.031,139.105 322.031,137.895
322.031,133.181 322.031,131.971 322.031,127.504 322.031,126.981 323.241,126.981 323.241,127.504 323.241,131.971
323.241,133.181 323.241,137.895 323.241,139.105 323.241,142.592 323.241,143.766 "/>
<path fill="#0095A8" d="M357.325,236.279c-0.445,0-0.835-0.12-1.132-0.32c-0.301-0.2-0.498-0.466-0.62-0.712
c-0.242-0.494-0.235-0.917-0.238-0.968v-1.672c-0.002-0.449,0.117-0.842,0.319-1.142c0.201-0.301,0.467-0.497,0.713-0.619
c0.494-0.242,0.917-0.235,0.968-0.238h17.349v-4.227h-35.117c-0.003,0-0.006,0-0.01,0c-1.49,0-2.666-0.381-3.553-0.973
c-0.89-0.592-1.479-1.381-1.863-2.149c-0.765-1.54-0.758-3.009-0.761-3.059v-55.623c-0.002-1.493,0.379-2.671,0.974-3.559
c0.593-0.889,1.383-1.477,2.151-1.861c1.542-0.765,3.011-0.758,3.062-0.761h81.492c0.004,0,0.007,0,0.011,0
c1.489,0,2.665,0.381,3.551,0.973c0.89,0.592,1.479,1.382,1.863,2.15c0.766,1.539,0.758,3.008,0.762,3.058V220.2l0,0
c0.001,1.494-0.38,2.671-0.974,3.559c-0.593,0.889-1.383,1.478-2.152,1.861c-1.541,0.765-3.011,0.758-3.061,0.761h-33.443v4.227
h16.419c0.003,0,0.007,0,0.01,0c0.444,0,0.834,0.119,1.132,0.319c0.301,0.2,0.498,0.467,0.62,0.712
c0.242,0.494,0.235,0.917,0.238,0.968v1.672c0.002,0.449-0.118,0.843-0.32,1.142c-0.2,0.301-0.467,0.498-0.712,0.62
c-0.495,0.242-0.918,0.234-0.968,0.238h-46.7C357.331,236.279,357.328,236.279,357.325,236.279 M356.544,234.273l0.001,0.01
l0.005,0.056l0.042,0.208c0.05,0.165,0.137,0.318,0.271,0.405c0.093,0.06,0.223,0.115,0.472,0.117h46.694l0.009-0.001l0.056-0.005
l0.209-0.042c0.165-0.05,0.318-0.137,0.406-0.271c0.06-0.093,0.115-0.222,0.116-0.471v-1.671v-0.004l-0.005-0.057l-0.043-0.207
c-0.049-0.166-0.136-0.318-0.271-0.406c-0.092-0.06-0.222-0.115-0.471-0.116h-17.629v-6.647h34.653l0.021-0.001l0.086-0.003
c0.077-0.004,0.193-0.012,0.339-0.029c0.291-0.033,0.698-0.101,1.146-0.236c0.902-0.27,1.938-0.798,2.614-1.814
c0.452-0.681,0.769-1.594,0.771-2.888l0,0v-55.623l-0.001-0.02l-0.003-0.086c-0.004-0.077-0.012-0.193-0.029-0.339
c-0.034-0.29-0.102-0.697-0.236-1.145c-0.271-0.9-0.799-1.935-1.817-2.611c-0.681-0.452-1.595-0.768-2.891-0.77h-81.492
l-0.021,0.001l-0.086,0.003c-0.078,0.004-0.194,0.012-0.339,0.029c-0.291,0.033-0.699,0.102-1.147,0.236
c-0.901,0.27-1.937,0.798-2.614,1.814c-0.452,0.681-0.768,1.594-0.77,2.888V220.2v0.02l0.004,0.086
c0.004,0.078,0.012,0.194,0.029,0.339c0.033,0.29,0.101,0.697,0.235,1.145c0.271,0.9,0.8,1.935,1.817,2.611
c0.681,0.452,1.596,0.768,2.892,0.77h36.327v6.647h-18.553h-0.009l-0.057,0.005l-0.208,0.043c-0.165,0.049-0.319,0.136-0.406,0.27
c-0.06,0.093-0.115,0.222-0.117,0.471V234.273 M357.341,231.818L357.341,231.818"/>
<path fill="#0095A8" d="M423.32,216.463h-84.706V163.02v-0.605h84.706V216.463 M339.824,163.625v51.628h82.286v-51.628H339.824
M339.219,163.02v0.605V163.02"/>
<path fill="#FFFFFF" d="M93.251,242.718h-1.889v-65.263h1.889v13.601h0.188c2.456-8.5,9.54-14.734,19.456-14.734
c12.845,0,20.685,10.672,20.685,25.311c0,13.602-7.273,25.502-20.685,25.502c-10.294,0-17.188-5.951-19.456-14.735h-0.188V242.718
L93.251,242.718z M131.691,201.633c0-12.466-6.234-23.422-18.796-23.422c-12.466,0-19.644,10.862-19.644,23.422
c0,15.018,7.839,23.612,19.644,23.612C126.213,225.245,131.691,212.873,131.691,201.633L131.691,201.633z"/>
<path fill="#FFFFFF" d="M141.139,202.106c0.189,13.033,5.384,23.139,19.173,23.139c10.012,0,17.379-5.572,18.984-16.055h1.889
c-1.323,11.144-9.634,17.945-20.684,17.945c-15.017,0.189-21.25-10.957-21.25-25.406c0-16.151,10.294-25.407,21.25-25.407
c15.112,0,21.817,12.467,21.251,25.784H141.139L141.139,202.106z M179.862,200.217c0.096-11.9-6.611-22.006-19.171-22.006
c-10.485,0-18.89,8.406-19.552,22.006H179.862L179.862,200.217z"/>
<path fill="#FFFFFF" d="M189.313,177.455h1.889v11.995h0.188c1.795-7.461,7.934-13.128,17.473-13.128
c10.106,0,17.284,6.234,17.284,17.473v32.206h-1.889v-31.923c0-11.239-7.178-15.867-15.395-15.867
c-11.616,0-17.661,9.539-17.661,20.306v27.484h-1.889V177.455L189.313,177.455z"/>
<polygon fill="#E31937" points="235.161,178.238 272.086,178.238 272.086,190.48 249.876,190.48 249.876,196.434 268.942,196.434
268.942,207.806 249.876,207.806 249.876,226.001 235.161,226.001 235.161,178.238 "/>
<polygon fill="#E31937" points="277.298,178.238 292.014,178.238 292.014,213.759 313.153,213.759 313.153,226.001
277.298,226.001 277.298,178.238 "/>
<path fill="#FFFFFF" d="M63.701,176.322c14.167,0,21.818,12.184,21.818,25.407c0,13.316-7.651,25.406-21.913,25.406
c-14.167,0-21.816-12.09-21.816-25.406C41.79,188.506,49.439,176.322,63.701,176.322L63.701,176.322z M63.701,225.245
c12.939,0,19.928-11.239,19.928-23.516c0-12.09-6.989-23.518-19.928-23.518c-13.128,0-20.022,11.428-20.022,23.518
C43.679,214.006,50.573,225.245,63.701,225.245L63.701,225.245z"/>
<polygon fill="#00B6B2" points="59.568,169.7 59.568,235.779 67.612,235.779 67.612,169.7 59.568,169.7 "/>
<path fill="#6BC9C7" d="M117.414,88.499c-5.343,0-9.409-1.345-12.462-3.382c-3.058-2.038-5.091-4.755-6.439-7.45
c-2.692-5.395-2.685-10.718-2.688-10.768V19.707c-0.002-5.349,1.343-9.418,3.382-12.474c2.038-3.057,4.754-5.091,7.45-6.438
c5.394-2.692,10.718-2.685,10.768-2.688v0.6v0.6l-0.119,0.002c-0.083,0.002-0.208,0.006-0.369,0.015
c-0.323,0.017-0.795,0.05-1.381,0.118c-1.172,0.135-2.799,0.406-4.603,0.948c-3.612,1.084-7.902,3.239-10.747,7.51
c-1.899,2.85-3.179,6.657-3.181,11.808v47.192l0.002,0.119c0.002,0.083,0.006,0.207,0.015,0.369
c0.016,0.323,0.05,0.795,0.117,1.381c0.136,1.172,0.407,2.799,0.948,4.603c1.084,3.612,3.239,7.902,7.51,10.747
c2.851,1.899,6.657,3.179,11.808,3.181h2.045l0.119-0.002c0.083-0.002,0.207-0.007,0.369-0.015c0.323-0.017,0.795-0.05,1.381-0.118
c1.172-0.135,2.799-0.406,4.603-0.947c3.612-1.084,7.902-3.239,10.747-7.51c1.899-2.851,3.179-6.657,3.181-11.808V19.707
l-0.002-0.119c-0.002-0.083-0.006-0.208-0.015-0.369c-0.016-0.324-0.05-0.795-0.118-1.381c-0.135-1.172-0.406-2.8-0.947-4.603
c-1.084-3.612-3.239-7.902-7.51-10.748c-2.851-1.898-6.657-3.179-11.808-3.181h-2.045v-0.6v-0.6h2.045c0.003,0,0.006,0,0.009,0
c5.344,0,9.41,1.344,12.464,3.382c3.057,2.038,5.091,4.754,6.438,7.45c2.693,5.395,2.685,10.719,2.689,10.769v47.192
c0.002,5.349-1.343,9.417-3.382,12.473c-2.038,3.057-4.755,5.091-7.45,6.438c-5.395,2.693-10.718,2.686-10.768,2.689h-2.045
C117.421,88.499,117.418,88.499,117.414,88.499"/>
<path fill="#6BC9C7" d="M136.002,64.666h-35.109V11.539v-0.6h35.109V64.666 M102.093,12.14v51.326h32.709V12.14H102.093
M101.493,11.539v0.6V11.539"/>
<path fill="#6BC9C7" d="M118.448,78.225L118.448,78.225L118.448,78.225L118.448,78.225 M118.448,78.225
c-1.696,0-3.069-1.374-3.07-3.069c0.001-1.696,1.374-3.069,3.07-3.07c1.695,0.001,3.068,1.374,3.069,3.07
C121.516,76.851,120.143,78.225,118.448,78.225v-0.6v-0.6c1.032-0.002,1.867-0.837,1.869-1.869
c-0.002-1.032-0.837-1.868-1.869-1.87c-1.033,0.002-1.868,0.838-1.87,1.87c0.002,1.032,0.837,1.867,1.87,1.869v0.6V78.225
L118.448,78.225"/>
<polyline fill="#6BC9C7" points="124.068,6.036 112.826,6.036 112.826,4.836 124.068,4.836 124.068,6.036 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -0,0 +1,13 @@
package jigsawx;
class JigsawMagicNumbers{
// move to external file
public static inline var dMore: Float = 12*2/1.5;
public static inline var dinout: Float = 5*2/1.5;
public static inline var ellipseSmallx: Float = 2*18/6/1.5;
public static inline var ellipseSmally: Float = 2*11/6/1.5;
public static inline var ellipseLargex: Float = 2*45/8/1.5;
public static inline var ellipseLargey: Float = 2*18*2/8/1.5;
public static inline var stepSize: Float = 10/1.5;
}

View File

@@ -0,0 +1,254 @@
package jigsawx;
import jigsawx.JigsawSideData;
import jigsawx.math.Vec2;
import jigsawx.JigsawMagicNumbers;
enum Compass{
NORTH;
SOUTH;
EAST;
WEST;
}
class JigsawPiece{
public var enabled: Bool;
private var curveBuilder: OpenEllipse;
private var stepAngle: Float;
private var centre: Vec2;
private var points: Array<Vec2>;
public var sideData: JigsawPieceData;
private var first: Vec2;
public var xy: Vec2;
public var wh: Vec2;
public var row: Int;
public var col: Int;
public function new( xy_: Vec2
, row: Int
, col: Int
, bubbleSize: Float
, lt: Vec2, rt: Vec2, rb: Vec2, lb: Vec2
, sideData_: JigsawPieceData
){
enabled = true;
xy = new Vec2( xy_.x, xy_.y );
this.row = row;
this.col = col;
sideData = sideData_;
points = [];
stepAngle = JigsawMagicNumbers.stepSize*Math.PI/180;
first = lt;
lt = lt.copy();
rt = rt.copy();
lb = lb.copy();
rb = rb.copy();
var edgeLeeway = lt.x;
if (sideData.north == null) {
lt.y = 0;
rt.y = 0;
}
if (sideData.east == null) {
rt.x += edgeLeeway;
rb.x += edgeLeeway;
}
if (sideData.south == null) {
lb.y += edgeLeeway;
rb.y += edgeLeeway;
}
if (sideData.west == null) {
lt.x = 0;
lb.x = 0;
}
// NORTH side
if( sideData.north != null ) createVertSide( lt, rt, bubbleSize, sideData.north, NORTH );
points.push( rt );
// EAST side
if( sideData.east != null ) createHoriSide( rt, rb, bubbleSize, sideData.east, EAST );
points.push( rb );
// SOUTH side
if( sideData.south != null ) createVertSide( rb, lb, bubbleSize, sideData.south, SOUTH );
points.push( lb );
// WEST side
if( sideData.west != null ) createHoriSide( lb, lt, bubbleSize, sideData.west, WEST );
points.push( lt );
var minX = Math.POSITIVE_INFINITY;
var minY = Math.POSITIVE_INFINITY;
var maxX = 0.0;
var maxY = 0.0;
for (point in points) {
if (point.x < minX)
minX = point.x;
if (point.y < minY)
minY = point.y;
if (point.x > maxX)
maxX = point.x;
if (point.y > maxY)
maxY = point.y;
}
wh = new Vec2(maxX, maxY);
// Crop the points so we don't make a bigger source rectangle than needed,
// and the origin will align with center of mass better
xy.add(minX, minY);
wh.subtract(minX, minY);
points = [for (point in points) {
point.copy().subtract(minX, minY);
}];
for (compass => points in bubblePoints) {
if (points != null) {
bubblePoints[compass] = [for (point in points) point.copy().subtract(minX, minY)];
}
}
}
public function getPoints(): Array<Vec2> {
return points;
}
public function getFirst(): Vec2 {
return first;
}
private function createVertSide( A: Vec2
, B: Vec2
, bubbleSize: Float
, side: JigsawSideData
, compass: Compass
){
drawSide( A.x + ( B.x - A.x )/2 + JigsawMagicNumbers.dMore/2 - side.squew*( JigsawMagicNumbers.dMore )
, A.y + ( B.y - A.y )/2 + JigsawMagicNumbers.dinout/2 - side.inout*( JigsawMagicNumbers.dinout )
, bubbleSize
, side
, compass
);
}
private function createHoriSide ( A: Vec2
, B: Vec2
, bubbleSize: Float
, side: JigsawSideData
, compass: Compass
){
drawSide( A.x + ( B.x - A.x )/2 + JigsawMagicNumbers.dinout/2 - side.inout*( JigsawMagicNumbers.dinout )
, A.y + ( B.y - A.y )/2 + JigsawMagicNumbers.dMore/2 - side.squew*( JigsawMagicNumbers.dMore )
, bubbleSize
, side
, compass
);
}
public var bubblePoints:Map<Compass,Array<Vec2>> = [];
private function drawSide( dx: Float, dy: Float, bubbleSize:Float, sideData: JigsawSideData, compass: Compass ){
var halfPI = Math.PI/2;
var dimensions = new Vec2();
var offsetCentre = new Vec2();
var bubble = sideData.bubble;
centre =
switch( compass )
{
case NORTH: new Vec2( dx, dy + bubbleSize*switch bubble{ case IN: 1; case OUT: -1; } );
case EAST: new Vec2( dx - bubbleSize*switch bubble{ case IN: 1; case OUT: -1; }, dy );
case SOUTH: new Vec2( dx, dy - bubbleSize*switch bubble{ case IN: 1; case OUT: -1; } );
case WEST: new Vec2( dx + bubbleSize*switch bubble{ case IN: 1; case OUT: -1; }, dy );
}
curveBuilder = new OpenEllipse();
curveBuilder.centre = centre;
// large Arc
dimensions.x = ( 1 + ( 0.5 - sideData.centreWide )/2 ) * JigsawMagicNumbers.ellipseLargex;
dimensions.y = ( 1 + ( 0.5 - sideData.centreHi )/2 ) * JigsawMagicNumbers.ellipseLargex;
curveBuilder.dimensions = dimensions;
curveBuilder.beginAngle = Math.PI/8;
curveBuilder.finishAngle = -Math.PI/8;
curveBuilder.stepAngle = stepAngle;
curveBuilder.rotation = switch bubble { case IN: 0; case OUT: Math.PI; }
switch( compass ){
case NORTH:
case EAST: curveBuilder.rotation += halfPI;
case SOUTH: curveBuilder.rotation += Math.PI;
case WEST: curveBuilder.rotation += 3*halfPI;
}
var secondPoints = curveBuilder.getRenderList();
if( bubble == IN ) secondPoints.reverse();
var theta = curveBuilder.beginAngle - curveBuilder.finishAngle + Math.PI;
var cosTheta = Math.cos( theta );
var sinTheta = Math.sin( theta );
var hyp = curveBuilder.getBeginRadius();
// left Arc
dimensions.x = ( 1 + ( 0.5 - sideData.leftWide )/2 ) * JigsawMagicNumbers.ellipseSmallx;
dimensions.y = ( 1 + ( 0.5 - sideData.leftHi )/2 ) * JigsawMagicNumbers.ellipseSmally;
curveBuilder.dimensions = dimensions;
curveBuilder.beginAngle = halfPI;
curveBuilder.finishAngle = -halfPI;
curveBuilder.stepAngle = stepAngle;
curveBuilder.rotation = theta + switch bubble { case IN: 0; case OUT: halfPI; };
switch( compass ){
case NORTH:
case EAST: curveBuilder.rotation += halfPI;
case SOUTH: curveBuilder.rotation += Math.PI;
case WEST: curveBuilder.rotation += 3*halfPI;
}
var hypLeft = hyp + curveBuilder.dimensions.x;
switch( compass ){
case NORTH:
offsetCentre.x = centre.x + hypLeft*cosTheta;
offsetCentre.y = centre.y + switch bubble { case IN: hypLeft*sinTheta; case OUT: -hypLeft*sinTheta; }
case EAST:
offsetCentre.x = centre.x + switch bubble { case IN: -hypLeft*cosTheta; case OUT: hypLeft*cosTheta; }
offsetCentre.y = centre.y + hypLeft*sinTheta;
case SOUTH:
offsetCentre.x = centre.x - hypLeft*cosTheta;
offsetCentre.y = centre.y - switch bubble { case IN: hypLeft*sinTheta; case OUT: - hypLeft*sinTheta; }
case WEST:
offsetCentre.x = centre.x + switch bubble { case IN: hypLeft*cosTheta; case OUT: -hypLeft*cosTheta; }
offsetCentre.y = centre.y - hypLeft*sinTheta;
}
curveBuilder.centre = offsetCentre;
var startPoint = curveBuilder.getBegin();
var firstPoints = curveBuilder.getRenderList();
if( sideData.bubble == OUT ) firstPoints.reverse();
firstPoints.pop();
firstPoints.pop();
secondPoints.shift();
secondPoints.shift();
secondPoints.shift();
points = points.concat( firstPoints.concat( secondPoints ) );
// right Arc
dimensions.x = ( 1 + ( 0.5 - sideData.rightWide )/2 ) * JigsawMagicNumbers.ellipseSmallx;
dimensions.y = ( 1 + ( 0.5 - sideData.rightHi )/2 ) * JigsawMagicNumbers.ellipseSmally;
curveBuilder.dimensions = dimensions;
curveBuilder.beginAngle = halfPI;
curveBuilder.finishAngle = -halfPI;
curveBuilder.stepAngle = stepAngle;
curveBuilder.rotation = theta + switch bubble { case IN: - halfPI; case OUT: Math.PI; };
switch( compass ){
case NORTH:
case EAST: curveBuilder.rotation += halfPI;
case SOUTH: curveBuilder.rotation += Math.PI;
case WEST: curveBuilder.rotation += 3*halfPI;
}
var hypRight = hyp + curveBuilder.dimensions.x;
switch( compass ){
case NORTH:
offsetCentre.x = centre.x - hypRight*cosTheta;
offsetCentre.y = centre.y + switch bubble { case IN: hypRight*sinTheta; case OUT: -hypRight*sinTheta; };
case EAST:
offsetCentre.x = centre.x + switch bubble { case IN: -hypLeft*cosTheta; case OUT: hypLeft*cosTheta; }
offsetCentre.y = centre.y - hypLeft*sinTheta;
case SOUTH:
offsetCentre.x = centre.x + hypRight*cosTheta;
offsetCentre.y = centre.y - switch bubble { case IN: hypRight*sinTheta; case OUT: -hypRight*sinTheta; };
case WEST:
offsetCentre.x = centre.x + switch bubble { case IN: hypLeft*cosTheta; case OUT: -hypLeft*cosTheta; }
offsetCentre.y = centre.y + hypLeft*sinTheta;
}
curveBuilder.centre = offsetCentre;
var thirdPoints = curveBuilder.getRenderList();
if( bubble == OUT ) thirdPoints.reverse();
thirdPoints.shift();
thirdPoints.shift();
points.pop();
points.pop();
points.pop();
bubblePoints[compass] = secondPoints;
points = points.concat( thirdPoints );
}
}

View File

@@ -0,0 +1,94 @@
package jigsawx;
import flixel.math.FlxRandom;
typedef JigsawPieceData = {
var north: JigsawSideData;
var east: JigsawSideData;
var south: JigsawSideData;
var west: JigsawSideData;
}
enum Bubble{
IN;
OUT;
}
class JigsawSideData{
// if the nobble is IN OUT or null ( flat side )
public var bubble: Bubble;
//offsets random multiplier
public var squew: Float;
// inout random multiplier
public var inout: Float;
//ellipse width and height random multiplier, drawn in the order left, centre, right
public var leftWide: Float;
public var leftHi: Float;
public var centreWide: Float;
public var centreHi: Float;
public var rightWide: Float;
public var rightHi: Float;
// returns half a jigsawPieceData, the other side is populated from piece above and from left
public static function halfPieceData(r:FlxRandom): JigsawPieceData{
#if !noRandom return { north: null, east: create(r), south: create(r), west: null };
// Test use -D noRandom
#else return { north: null, east: createSimple(r), south: createSimple(r), west: null };
#end
}
private static function createBubble(r:FlxRandom): Bubble {
return r.bool() ? IN: OUT;
}
private static function swapBubble( bubble: Bubble ): Bubble {
if( bubble == OUT ) return IN;
if( bubble == IN ) return OUT;
return null;
}
// reflect side
public static function reflect( j: JigsawSideData ): JigsawSideData {
var side = new JigsawSideData();
side.bubble = swapBubble( j.bubble );
//left right or up dawn offset.
side.squew = j.squew;
// in out
side.inout = j.inout;
// radii of ellipses
side.leftWide = j.rightWide;
side.leftHi = j.rightHi;
side.centreWide = j.centreWide;
side.centreHi = j.centreHi;
side.rightWide = j.leftWide;
side.rightHi = j.leftHi;
return side;
}
// when you want to test no random.
public static function createSimple(r:FlxRandom): JigsawSideData {
var side = new JigsawSideData();
side.bubble = createBubble(r);
//left right or up dawn offset.
side.squew = 0.5;
// in out
side.inout = 0.5;
// radii of ellipses
side.leftWide = 0.5;
side.leftHi = 0.5;
side.centreWide = 0.5;
side.centreHi = 0.5;
side.rightWide = 0.5;
side.rightHi = 0.5;
return side;
}
public static function create(r:FlxRandom): JigsawSideData {
var side = new JigsawSideData();
side.bubble = createBubble(r);
//left right or up dawn offset.
side.squew = r.float();
// in out
side.inout = r.float();
// radii of ellipses
side.leftWide = r.float();
side.leftHi = r.float();
side.centreWide = r.float();
side.centreHi = r.float();
side.rightWide = r.float();
side.rightHi = r.float();
return side;
}
// use create instead
private function new(){}
}

View File

@@ -0,0 +1,112 @@
package jigsawx ;
import jigsawx.OpenEllipse ;
import jigsawx.JigsawPiece ;
import jigsawx.math.Vec2;
import jigsawx.JigsawSideData;
import kiss.List;
import flixel.math.FlxRandom;
class Jigsawx {
private var rows: Int;
private var cols: Int;
private var pieces: kiss.List<kiss.List<JigsawPiece>>;
public var jigs: Array<JigsawPiece>;
private var sides: Array<Array<JigsawPieceData>>;
private var lt: Float;
private var rt: Float;
private var rb: Float;
private var lb: Float;
private var dx: Float;
private var dy: Float;
private var length: Int;
public function new( pieceWidth: Float
, pieceHeight: Float
, totalWidth: Float
, totalHeight: Float
, edgeLeeway: Float
, bubbleSize: Float
, rows_: Int
, cols_: Int
, r: FlxRandom) {
pieces = [];
jigs = [];
sides = [];
dx = pieceWidth;
dy = pieceHeight;
rows = rows_;
cols = cols_;
//corners, theoretically JigsawSideData could be modified to allow these to have a random element.
var xy = new Vec2( 0, 0 );
var lt = new Vec2( edgeLeeway, edgeLeeway );
var rt = new Vec2( edgeLeeway + dx, edgeLeeway );
var rb = new Vec2( edgeLeeway + dx, dy + edgeLeeway );
var lb = new Vec2( edgeLeeway, dy + edgeLeeway );
length = 0;
var last: JigsawPieceData;
for( row in 0...rows ){
last = { north: null, east: null, south: null, west: null };
sides.push( new Array() );
for( col in 0...cols ){
var jigsawPiece = JigsawSideData.halfPieceData(r);
if( last.east != null ) jigsawPiece.west = JigsawSideData.reflect( last.east );
if( col == cols - 1 ) jigsawPiece.east = null;
sides[ row ][ col ] = jigsawPiece;
last = jigsawPiece;
length++;
}
}
for( col in 0...cols ){
last = { north: null, east: null, south: null, west: null };
for( row in 0...rows ){
var jigsawPiece = sides[ row ][ col ];
if( last.south != null ) jigsawPiece.north = JigsawSideData.reflect( last.south );
if( row == rows - 1 ) jigsawPiece.south = null;
last = jigsawPiece;
}
}
var jig: JigsawPiece;
for( row in 0...rows ){
pieces.push( new Array() );
for( col in 0...cols ){
jig = new JigsawPiece( xy, row, col, bubbleSize, lt, rt, rb, lb, sides[ row ][ col ] );
pieces[ row ][ col ] = jig;
jigs.push( jig );
xy.x += dx;
}
xy.x = 0;
xy.y += dy;
}
// Assert that this puzzle's geometry contains the actual corners of the image:
var corners = ["top left", "top right", "bottom left", "bottom right"];
function contains(p:JigsawPiece, v:Vec2) {
var minOffset = Math.POSITIVE_INFINITY;
for (pt in p.getPoints()) {
var offset = Math.abs(pt.x - (v.x - p.xy.x)) + Math.abs(pt.y - (v.y - p.xy.y));
if (offset < minOffset)
minOffset = offset;
if (offset < 1)
return true;
}
return false;
}
var containsCorners = [
contains(pieces[0][0], new Vec2(0, 0)),
contains(pieces[0][-1], new Vec2(totalWidth, 0)),
contains(pieces[-1][0], new Vec2(0, totalHeight)),
contains(pieces[-1][-1], new Vec2(totalWidth, totalHeight))
];
var containsAllCorners = true;
for (i in 0...corners.length) {
if (!containsCorners[i]) {
trace('missing ${corners[i]} corner');
containsAllCorners = false;
}
}
if (!containsAllCorners) {
#if debug
throw "jigsawX geometry doesn't align with the whole image dimensions!";
#end
}
}
}

View File

@@ -0,0 +1,313 @@
/*
* Copyright (c) 2012, Justinfront Ltd
* author: Justin L Mills
* email: JLM at Justinfront dot net
* created: 17 June 2012
* updated to openfl: 23 Feburary 2014
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Justinfront Ltd nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Justinfront Ltd ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Justinfront Ltd BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jigsawx;
import flash.Lib;
import flash.display.Sprite ;
import flash.display.Graphics;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.display.Loader;
import flash.display.DisplayObject;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.geom.Rectangle;
import flash.geom.Point;
import flash.display.PixelSnapping;
import flash.geom.Matrix;
import flash.events.IOErrorEvent;
//import neash.display.BitmapInt32;
import haxe.Timer;
import flash.net.URLRequest;
import jigsawx.JigsawPiece ;
import jigsawx.Jigsawx;
import jigsawx.math.Vec2;
class JigsawxOpenfl extends Sprite
{
private var holder : Sprite;
private var hit: Sprite;
private var jigsawx : Jigsawx;
private var videoSource: Sprite;
private var wid: Float;
private var hi: Float;
private var rows: Int;
private var cols: Int;
private var count: Int;
private var atimer: Timer;
private var depth: Int;
private var tiles: Array<Sprite>;
private var surfaces: Array<Bitmap>;
private var offset: Array<Vec2>;
private var current: Sprite;
private var spCloth: Sprite;
private var loader: Loader;
private inline static var imageSrc: String = "tablecloth.jpg";
public function new()
{
super();
current = Lib.current;
holder = new Sprite();
holder.x = 0;
holder.y = 0;
current.addChild( holder ) ;
count = 0;
rows = 7;
cols = 10;
wid = 45;
hi = 45;
createVisuals();
tableClothDisplay();
Lib.current.addEventListener( MouseEvent.MOUSE_UP, allTilesStop );
}
public function allTilesStop( e: MouseEvent )
{
// TODO: Need to add is close snap code for this case...
for( all in tiles ) all.stopDrag();
}
public function tableClothDisplay()
{
spCloth = new Sprite();
loader = new Loader();
trace( 'tableClothDisplay' );
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, copyAcross );
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, traceNotFound );
loader.load( new URLRequest( 'assets/' + imageSrc ) );
#if showImageSource
holder.addChild( spCloth );
#end
}
private function traceNotFound( e: IOErrorEvent )
{
trace( 'error ' + e );
}
private function copyAcross( e: Event )
{
trace( 'copyAccoss ');
count++;
var bmp: Bitmap = cast loader.content;
trace( bmp );
spCloth.addChild( new Bitmap( bmp.bitmapData ) );
//if( count > 1000 ) atimer.stop();
var off: Vec2;
var xy = new Vec2( 0, 0 );
var count = 0;
for( row in 0...rows )
{
for( col in 0...cols )
{
off = offset[ count ];
// optimisation could try render blitting to single surface and implement dragging in the same way as javascript.
// scale 1.2 times
surfaces[ count ].bitmapData.draw( spCloth, new Matrix( 1.2, 0, 0, 1.2, -xy.x - off.x, -xy.y - off.y) );
xy.x += wid;
count++;
}
xy.x = 0;
xy.y += hi;
}
}
public function createVisuals()
{
var sp: Sprite;
var maskSp: Sprite;
var tile: Sprite;
var surface: Graphics;
tiles = [];
surfaces = [];
offset = [];
var first: Vec2;
jigsawx = new Jigsawx( wid, hi, rows, cols );
depth = 0;
for( jig in jigsawx.jigs )
{
// create sprite and surface and mask
sp = new Sprite();
tiles.push( sp );
holder.addChild( sp );
tile = new Sprite();
sp.addChild( tile );
//sp.fill = '#ffffff';
sp.x = jig.xy.x;
sp.y = jig.xy.y;
maskSp = new Sprite();
tile.mask = maskSp;
maskSp.x = -wid/2;
maskSp.y = -hi/2;
surface = maskSp.graphics;
sp.addChild( maskSp );
// local copies so that local functions can get the the current loop variables, not sure if they are all needed.
var tempSp = sp;
var wid_ = wid/2;
var hi_ = hi/2;
var ajig = jig;
// Select some pieces out of place.
if( Math.random()*5 > 2 )
{
sp.x = 900 - Math.random()*400;
sp.y = 400 - Math.random()*400;
sp.alpha = 0.7;
drawEdge( surface, jig, 0x0000ff );
sp.addEventListener( MouseEvent.MOUSE_DOWN, function( e: MouseEvent )
{
tempSp.parent.addChild( tempSp );
tempSp.startDrag();
});
sp.addEventListener( MouseEvent.MOUSE_UP, function( e: MouseEvent )
{
if( Math.abs( ajig.xy.x - tempSp.x ) < ( wid_ + hi_ )/4 && Math.abs( ajig.xy.y - tempSp.y ) < ( wid_ + hi_ )/4 )
{
tempSp.x = ajig.xy.x;
tempSp.y = ajig.xy.y;
tempSp.alpha = 1;
jig.enabled = false;
tempSp.mouseEnabled = false;
tempSp.mouseChildren = false;
tempSp.buttonMode = false;
tempSp.useHandCursor = false;
}
tempSp.stopDrag();
});
}
else
{
maskSp.alpha = 0;
jig.enabled = false;
tempSp.mouseEnabled = true;
tempSp.mouseChildren = true;
tempSp.buttonMode = true;
tempSp.useHandCursor = true;
drawEdge( surface, jig, 0x000000 );
}
// significant change required for nme
var bounds = maskSp.getBounds( sp );
tile.x = bounds.x;
tile.y = bounds.y;
var tileW = Std.int( maskSp.width );
var tileH = Std.int( maskSp.height );
// for alpha colors you can't use an Int directly in nme BitmapData.createColor( 0xff,0xffffff )
var bd = new BitmapData( tileW, tileH, true, 0xffffffff );
var bm = new Bitmap( bd, PixelSnapping.ALWAYS, true );
// May not need this line... possibly change bm to not transparent.
bd.fillRect( new Rectangle( 0, 0, tileW, tileH ), 0x000000ff );
tile.addChild( bm );
surfaces.push( bm );
offset.push( new Vec2( bounds.x, bounds.y ) );
}
}
public function drawEdge( surface: Graphics, jig: JigsawPiece, c: Int )
{
surface.lineStyle( 1, c, 1 );
surface.beginFill( c, 1 );
var first = jig.getFirst();
surface.moveTo( first.x, first.y );
for( v in jig.getPoints() ) { surface.lineTo( v.x, v.y ); }
surface.endFill();
}
}

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 nanjizal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,51 @@
package jigsawx;
import jigsawx.ds.CircleIter;
import jigsawx.math.Vec2;
class OpenEllipse {
public var rotation: Float;
public var beginAngle: Float;
public var finishAngle: Float;
public var stepAngle: Float;
public var centre: Vec2;
public var dimensions: Vec2;
private var circleIter: CircleIter;
private var _points: Array<Vec2>;
public function new(){}
public function getBegin(): Vec2 {
return createPoint( centre, dimensions, beginAngle );
}
public function getFinish(): Vec2 {
return createPoint( centre, dimensions, finishAngle );
}
public function getBeginRadius(){
return pointDistance( centre, getBegin() );
}
public function getFinishRadius(){
return pointDistance( centre, getFinish() );
}
private function pointDistance( A: Vec2, B: Vec2 ): Float {
var dx = A.x - B.x;
var dy = A.y - B.y;
return Math.sqrt( dx*dx + dy*dy );
}
public function setUp(){
circleIter = CircleIter.pi2pi( beginAngle, finishAngle, stepAngle );
}
public function getRenderList(): Array<Vec2> {
_points = new Array();
if( circleIter == null ) setUp();
_points.push( createPoint( centre, dimensions, beginAngle ) );
for( theta in CircleIter.pi2pi( beginAngle, finishAngle, stepAngle ).reset() ){
_points.push( createPoint( centre, dimensions, theta ) );
}
return _points;
}
public function createPoint( centre: Vec2, dimensions: Vec2, theta: Float ): Vec2 {
var offSetA = 3*Math.PI/2 - rotation;// arange so that angle moves from 0... could tidy up dxNew and dyNew!
var dx = dimensions.x*Math.sin( theta );// select the relevant sin cos so that 0 is upwards.
var dy = -dimensions.y*Math.cos( theta );
var dxNew = centre.x -dx*Math.sin( offSetA ) + dy*Math.cos( offSetA );
var dyNew = centre.y -dx*Math.cos( offSetA ) - dy*Math.sin( offSetA );
return new Vec2( dxNew, dyNew );
}
}

View File

@@ -0,0 +1,11 @@
# JigsawX
WIP - needs reoganising folders.
Jigsaw generation engine, many attributes are adjustable.
versions: NME / OpenFL / Swing / Flash / Javascript ( uses div's and canvas ).
[Demo Haxe Javascript Jigsaw](https://rawgit.com/nanjizal/JigsawX/master/bin/JigsawDivtastic.html)
![jigsawgrab](https://user-images.githubusercontent.com/20134338/27836978-c8e112fc-60d9-11e7-857c-12cd40216f33.png)

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<project>
<meta title="JigsawX" package="net.justinfront.jigsawx" version="1.0.0" company="justinfront" />
<app main="jigsawxtargets.hxopenfl.JigsawxOpenfl" path="openfl" file="Jigsawx" />
<source path="src" />
<haxelib name="openfl" />
<assets path="Assets" rename="assets" exclude="openfl.svg" />
<icon path="Assets/openfl.svg" />
</project>

View File

@@ -0,0 +1,18 @@
#-cmd lime test windows
#-cmd lime test windows -neko
#-cmd lime test mac
#--next
-cmd haxelib run nme cpp -bin binNme
#-cmd lime test mac -neko
#-cmd lime test linux
#-cmd lime test linux -neko
#-cmd lime test ios
#-cmd lime test ios -simulator
#-cmd lime test android
#-cmd lime test blackberry
#-cmd lime test blackberry -simulator
#-cmd lime test tizen
#-cmd lime test tizen -simulator
#-cmd lime test flash
#-cmd lime test html5

View File

@@ -0,0 +1,61 @@
package jigsawx.ds;
enum Sign{
UP;
DOWN;
}
class CircleIter {
var begin: Float;
var fin: Float;
var step: Float;
var min: Float;
var max: Float;
var current: Float;
var onDirection: Sign;
public static function pi2( begin_: Float
, fin_: Float
, step_: Float
){
return new CircleIter( begin_, fin_, step_, 0, 2*Math.PI );
}
public static function pi2pi( begin_: Float
, fin_: Float
, step_: Float
){
return new CircleIter( begin_, fin_, step_, -Math.PI, Math.PI );
}
public function new ( begin_: Float
, fin_: Float
, step_: Float
, min_: Float
, max_: Float
){
begin = begin_;
current = begin;
fin = fin_;
step = step_;
min = min_;
max = max_;
onDirection = ( step > 0 )? UP: DOWN;
}
public function reset(): CircleIter{
current = begin;
return this;
}
public function hasNext(): Bool {
switch onDirection {
case UP:
return ( ( current < fin && current + step > fin ) || current == fin )? false: true;
case DOWN:
return ( ( current > fin && (( current - step ) < fin) )|| current == fin )? false: true;
}
}
public function next() {
current += step;
switch onDirection{
case UP: if( current > max ) current = min + current - max;
case DOWN: if( current < min ) current = max + current - min;
}
if( !hasNext() ) return fin;
return current;
}
}

View File

@@ -0,0 +1,25 @@
package jigsawx.math;
class Vec2{
public var x: Float;
public var y: Float;
public function new( x_ = .0, y_ = .0 ){
x = x_;
y = y_;
}
public function copy() {
return new Vec2(x, y);
}
public function add(dx:Float, dy:Float) {
x += dx;
y += dy;
return this;
}
public function subtract(dx:Float, dy:Float) {
x -= dx;
y -= dy;
return this;
}
public function toString() {
return '(${x}, ${y})';
}
}