Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: prevostc/ion-catan
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.0
Choose a base ref
...
head repository: prevostc/ion-catan
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref

Commits on Jan 10, 2015

  1. Copy the full SHA
    e769eac View commit details
  2. Copy the full SHA
    63deff4 View commit details
  3. Copy the full SHA
    9e09a5c View commit details
  4. add hexagon type hierarchy

    prevostc committed Jan 10, 2015
    Copy the full SHA
    5678b68 View commit details
  5. Copy the full SHA
    cbf4a4f View commit details
  6. Copy the full SHA
    5dcecf5 View commit details
  7. Copy the full SHA
    6b96cdb View commit details
  8. Copy the full SHA
    2612d54 View commit details
  9. Android exception

    prevostc committed Jan 10, 2015
    Copy the full SHA
    227fcaa View commit details
  10. removed console.log

    prevostc committed Jan 10, 2015
    Copy the full SHA
    7c72680 View commit details
  11. fixed jshint warnings

    prevostc committed Jan 10, 2015
    Copy the full SHA
    474d642 View commit details
  12. Copy the full SHA
    8f80bc6 View commit details
  13. prepare to release 1.0.0

    prevostc committed Jan 10, 2015
    Copy the full SHA
    990167d View commit details

Commits on Jan 11, 2015

  1. Update sources version

    prevostc committed Jan 11, 2015
    Copy the full SHA
    9e9e5f4 View commit details
  2. Updated app name

    prevostc committed Jan 11, 2015
    Copy the full SHA
    201f9b9 View commit details
  3. Copy the full SHA
    49982c1 View commit details
  4. Copy the full SHA
    278a524 View commit details
  5. Copy the full SHA
    7686cf9 View commit details
  6. Copy the full SHA
    4275e66 View commit details

Commits on Jan 12, 2015

  1. integrate pixi ui framework

    prevostc committed Jan 12, 2015
    Copy the full SHA
    048e229 View commit details

Commits on Jan 14, 2015

  1. New UI system

    prevostc committed Jan 14, 2015
    Copy the full SHA
    24afcd6 View commit details

Commits on Jan 18, 2015

  1. Copy the full SHA
    4252cb8 View commit details

Commits on Jan 22, 2015

  1. Copy the full SHA
    9b96882 View commit details
  2. optimise for small screens

    prevostc committed Jan 22, 2015
    Copy the full SHA
    b45261f View commit details
  3. Copy the full SHA
    677389c View commit details
  4. Copy the full SHA
    93bd792 View commit details
  5. Copy the full SHA
    8d5fb21 View commit details

Commits on Mar 2, 2015

  1. Added favorites tab

    prevostc committed Mar 2, 2015
    Copy the full SHA
    4566ac1 View commit details
  2. Copy the full SHA
    058d87e View commit details
  3. fix high def ui states

    prevostc committed Mar 2, 2015
    Copy the full SHA
    1434cdb View commit details
  4. fix header button

    prevostc committed Mar 2, 2015
    Copy the full SHA
    fdf5288 View commit details
  5. version upgrade: favorites

    prevostc committed Mar 2, 2015
    Copy the full SHA
    d7585b2 View commit details
  6. Copy the full SHA
    7ba7e9b View commit details

Commits on Mar 4, 2015

  1. Copy the full SHA
    0258208 View commit details
  2. Copy the full SHA
    64f6bcc View commit details
  3. V1.1.1

    prevostc committed Mar 4, 2015
    Copy the full SHA
    2c38de6 View commit details
  4. Copy the full SHA
    69b5f9c View commit details

Commits on Mar 6, 2015

  1. Copy the full SHA
    027b721 View commit details
  2. bottom tabs everywhere

    prevostc committed Mar 6, 2015
    Copy the full SHA
    a9f7392 View commit details
  3. add a home screen tutorial

    prevostc committed Mar 6, 2015
    Copy the full SHA
    1e6079a View commit details

Commits on Mar 7, 2015

  1. minify everything

    prevostc committed Mar 7, 2015
    Copy the full SHA
    32051fb View commit details
  2. minify everything

    prevostc committed Mar 7, 2015
    Copy the full SHA
    a0e9a45 View commit details
  3. Copy the full SHA
    cc63f8d View commit details
  4. remove commited libs

    prevostc committed Mar 7, 2015
    Copy the full SHA
    ddcdf58 View commit details
  5. add build system

    prevostc committed Mar 7, 2015
    Copy the full SHA
    a8262ee View commit details
  6. Copy the full SHA
    d098258 View commit details
  7. smoother favorites screen

    prevostc committed Mar 7, 2015
    Copy the full SHA
    2654768 View commit details
  8. concatenate html templates

    prevostc committed Mar 7, 2015
    Copy the full SHA
    9ebba5b View commit details
  9. Copy the full SHA
    3ee5c1f View commit details
  10. remove favorite from map

    prevostc committed Mar 7, 2015
    Copy the full SHA
    314ecff View commit details
Showing with 2,174 additions and 130,288 deletions.
  1. +11 −0 .gitignore
  2. +26 −0 README.md
  3. +13 −5 bower.json
  4. +53 −17 config.xml
  5. +14 −0 features/generate.feature
  6. +15 −0 features/helpers/appium-servers.js
  7. +7 −0 features/helpers/apps.js
  8. +46 −0 features/helpers/capabilities.js
  9. +18 −0 features/helpers/logging.js
  10. +13 −0 features/helpers/setup.js
  11. +32 −0 features/step_definition/global.js
  12. +31 −0 features/step_definition/ionic.js
  13. +103 −0 features/support/world.js
  14. +13 −0 features/tabs.feature
  15. +134 −35 gulpfile.js
  16. 0 hooks/README.md
  17. +28 −0 hooks/after_prepare/020_remove_sass_from_platforms.js
  18. +34 −0 hooks/after_prepare/025_remove_non_dist_from_platforms.js
  19. +23 −0 hooks/before_platform_add/init_directories.js
  20. +72 −0 hooks/before_prepare/02_jshint.js
  21. +9 −0 hooks/before_prepare/15_run_gulp_build_tasks.js
  22. BIN icon.png
  23. BIN icons.xcf
  24. +6 −3 ionic.project
  25. +32 −9 package.json
  26. BIN resources/android/icon/drawable-hdpi-icon.png
  27. BIN resources/android/icon/drawable-ldpi-icon.png
  28. BIN resources/android/icon/drawable-mdpi-icon.png
  29. BIN resources/android/icon/drawable-xhdpi-icon.png
  30. BIN resources/android/icon/drawable-xxhdpi-icon.png
  31. BIN resources/android/icon/drawable-xxxhdpi-icon.png
  32. BIN resources/android/splash/drawable-port-hdpi-screen.png
  33. BIN resources/android/splash/drawable-port-ldpi-screen.png
  34. BIN resources/android/splash/drawable-port-mdpi-screen.png
  35. BIN resources/android/splash/drawable-port-xhdpi-screen.png
  36. BIN resources/icon.png
  37. BIN resources/ios/icon/icon-40.png
  38. BIN resources/ios/icon/icon-50.png
  39. BIN resources/ios/icon/icon-60.png
  40. BIN resources/ios/icon/icon-72.png
  41. BIN resources/ios/icon/icon-76.png
  42. BIN resources/ios/icon/icon-small.png
  43. BIN resources/ios/icon/icon.png
  44. BIN resources/ios/splash/Default-568h@2x~iphone.png
  45. BIN resources/ios/splash/Default-667h.png
  46. BIN resources/ios/splash/Default-Portrait~ipad.png
  47. BIN resources/ios/splash/Default@2x~iphone.png
  48. BIN resources/ios/splash/Default~iphone.png
  49. BIN resources/splash.png
  50. +39 −0 www/css/style.css
  51. BIN www/img/desert.png
  52. BIN www/img/empty.png
  53. BIN www/img/field.png
  54. BIN www/img/forest.png
  55. BIN www/img/hills.png
  56. BIN www/img/mountain.png
  57. BIN www/img/number.png
  58. BIN www/img/ocean.png
  59. BIN www/img/pasture.png
  60. +9 −25 www/index.html
  61. +87 −54 www/js/app.js
  62. +10 −1 www/js/catan/js/Position.js
  63. +1 −25 www/js/catan/js/catan.js
  64. +111 −0 www/js/catan/js/generator/generator.harbor.js
  65. +31 −0 www/js/catan/js/generator/generator.js
  66. +92 −0 www/js/catan/js/generator/generator.land.js
  67. +173 −0 www/js/catan/js/generator/generator.number.js
  68. +69 −7 www/js/catan/js/hexagon.js
  69. +73 −349 www/js/catan/js/map.js
  70. +12 −5 www/js/catan/js/tools.js
  71. +187 −17 www/js/catan/js/ui.js
  72. +228 −28 www/js/controllers.js
  73. +223 −11 www/js/services.js
  74. +0 −19 www/lib/angular-animate/.bower.json
  75. +0 −77 www/lib/angular-animate/README.md
  76. +0 −2,137 www/lib/angular-animate/angular-animate.js
  77. +0 −33 www/lib/angular-animate/angular-animate.min.js
  78. +0 −8 www/lib/angular-animate/angular-animate.min.js.map
  79. +0 −9 www/lib/angular-animate/bower.json
  80. +0 −26 www/lib/angular-animate/package.json
  81. +0 −41 www/lib/angular-local-storage/.bower.json
  82. +0 −3 www/lib/angular-local-storage/.bowerrc
  83. +0 −1 www/lib/angular-local-storage/.gitattributes
  84. +0 −8 www/lib/angular-local-storage/.gitignore
  85. +0 −9 www/lib/angular-local-storage/.travis.yml
  86. +0 −8 www/lib/angular-local-storage/CHANGELOG.md
  87. +0 −8 www/lib/angular-local-storage/LICENSE
  88. +0 −357 www/lib/angular-local-storage/README.md
  89. +0 −31 www/lib/angular-local-storage/bower.json
  90. +0 −27 www/lib/angular-local-storage/demo/demo-app.js
  91. +0 −15 www/lib/angular-local-storage/demo/demo-style.css
  92. +0 −154 www/lib/angular-local-storage/demo/demo.html
  93. +0 −455 www/lib/angular-local-storage/dist/angular-local-storage.js
  94. +0 −7 www/lib/angular-local-storage/dist/angular-local-storage.min.js
  95. +0 −38 www/lib/angular-local-storage/package.json
  96. +0 −19 www/lib/angular-sanitize/.bower.json
  97. +0 −77 www/lib/angular-sanitize/README.md
  98. +0 −680 www/lib/angular-sanitize/angular-sanitize.js
  99. +0 −16 www/lib/angular-sanitize/angular-sanitize.min.js
  100. +0 −8 www/lib/angular-sanitize/angular-sanitize.min.js.map
  101. +0 −9 www/lib/angular-sanitize/bower.json
  102. +0 −26 www/lib/angular-sanitize/package.json
  103. +0 −33 www/lib/angular-ui-router/.bower.json
  104. +0 −197 www/lib/angular-ui-router/CHANGELOG.md
  105. +0 −65 www/lib/angular-ui-router/CONTRIBUTING.md
  106. +0 −21 www/lib/angular-ui-router/LICENSE
  107. +0 −243 www/lib/angular-ui-router/README.md
  108. +0 −126 www/lib/angular-ui-router/api/angular-ui-router.d.ts
  109. +0 −23 www/lib/angular-ui-router/bower.json
  110. +0 −4,232 www/lib/angular-ui-router/release/angular-ui-router.js
  111. +0 −7 www/lib/angular-ui-router/release/angular-ui-router.min.js
  112. +0 −292 www/lib/angular-ui-router/src/common.js
  113. +0 −252 www/lib/angular-ui-router/src/resolve.js
  114. +0 −1,373 www/lib/angular-ui-router/src/state.js
  115. +0 −268 www/lib/angular-ui-router/src/stateDirectives.js
  116. +0 −39 www/lib/angular-ui-router/src/stateFilters.js
  117. +0 −110 www/lib/angular-ui-router/src/templateFactory.js
  118. +0 −1,036 www/lib/angular-ui-router/src/urlMatcherFactory.js
  119. +0 −413 www/lib/angular-ui-router/src/urlRouter.js
  120. +0 −71 www/lib/angular-ui-router/src/view.js
  121. +0 −302 www/lib/angular-ui-router/src/viewDirective.js
  122. +0 −52 www/lib/angular-ui-router/src/viewScroll.js
  123. +0 −17 www/lib/angular/.bower.json
  124. +0 −67 www/lib/angular/README.md
  125. +0 −13 www/lib/angular/angular-csp.css
  126. +0 −26,000 www/lib/angular/angular.js
  127. +0 −250 www/lib/angular/angular.min.js
  128. BIN www/lib/angular/angular.min.js.gzip
  129. +0 −8 www/lib/angular/angular.min.js.map
  130. +0 −8 www/lib/angular/bower.json
  131. +0 −25 www/lib/angular/package.json
  132. +0 −46 www/lib/ionic/.bower.json
  133. +0 −15 www/lib/ionic/README.md
  134. +0 −37 www/lib/ionic/bower.json
  135. +0 −7,013 www/lib/ionic/css/ionic.css
  136. +0 −18 www/lib/ionic/css/ionic.min.css
  137. BIN www/lib/ionic/fonts/ionicons.eot
  138. +0 −1,899 www/lib/ionic/fonts/ionicons.svg
  139. BIN www/lib/ionic/fonts/ionicons.ttf
  140. BIN www/lib/ionic/fonts/ionicons.woff
  141. +0 −11,483 www/lib/ionic/js/ionic-angular.js
  142. +0 −18 www/lib/ionic/js/ionic-angular.min.js
  143. +0 −52,387 www/lib/ionic/js/ionic.bundle.js
  144. +0 −386 www/lib/ionic/js/ionic.bundle.min.js
  145. +0 −7,811 www/lib/ionic/js/ionic.js
  146. +0 −17 www/lib/ionic/js/ionic.min.js
  147. +0 −92 www/lib/ionic/scss/_action-sheet.scss
  148. +0 −48 www/lib/ionic/scss/_animations.scss
  149. +0 −24 www/lib/ionic/scss/_backdrop.scss
  150. +0 −62 www/lib/ionic/scss/_badge.scss
  151. +0 −373 www/lib/ionic/scss/_bar.scss
  152. +0 −54 www/lib/ionic/scss/_button-bar.scss
  153. +0 −252 www/lib/ionic/scss/_button.scss
  154. +0 −176 www/lib/ionic/scss/_checkbox.scss
  155. +0 −310 www/lib/ionic/scss/_form.scss
  156. +0 −143 www/lib/ionic/scss/_grid.scss
  157. +0 −821 www/lib/ionic/scss/_items.scss
  158. +0 −125 www/lib/ionic/scss/_list.scss
  159. +0 −50 www/lib/ionic/scss/_loading.scss
  160. +0 −64 www/lib/ionic/scss/_menu.scss
  161. +0 −624 www/lib/ionic/scss/_mixins.scss
  162. +0 −94 www/lib/ionic/scss/_modal.scss
  163. +0 −59 www/lib/ionic/scss/_platform.scss
  164. +0 −168 www/lib/ionic/scss/_popover.scss
  165. +0 −105 www/lib/ionic/scss/_popup.scss
  166. +0 −11 www/lib/ionic/scss/_progress.scss
  167. +0 −57 www/lib/ionic/scss/_radio.scss
  168. +0 −122 www/lib/ionic/scss/_range.scss
  169. +0 −365 www/lib/ionic/scss/_reset.scss
  170. +0 −365 www/lib/ionic/scss/_scaffolding.scss
  171. +0 −141 www/lib/ionic/scss/_select.scss
  172. +0 −56 www/lib/ionic/scss/_slide-box.scss
  173. +0 −29 www/lib/ionic/scss/_split-pane.scss
  174. +0 −494 www/lib/ionic/scss/_tabs.scss
  175. +0 −138 www/lib/ionic/scss/_toggle.scss
  176. +0 −163 www/lib/ionic/scss/_transitions.scss
  177. +0 −163 www/lib/ionic/scss/_type.scss
  178. +0 −250 www/lib/ionic/scss/_util.scss
  179. +0 −722 www/lib/ionic/scss/_variables.scss
  180. +0 −51 www/lib/ionic/scss/ionic.scss
  181. +0 −77 www/lib/ionic/scss/ionicons/_ionicons-animation.scss
  182. +0 −27 www/lib/ionic/scss/ionicons/_ionicons-font.scss
  183. +0 −1,209 www/lib/ionic/scss/ionicons/_ionicons-icons.scss
  184. +0 −609 www/lib/ionic/scss/ionicons/_ionicons-variables.scss
  185. +0 −11 www/lib/ionic/scss/ionicons/ionicons.scss
  186. +9 −0 www/templates/tab-favorites-view.html
  187. +30 −0 www/templates/tab-favorites.html
  188. +21 −3 www/templates/tab-map.html
  189. +23 −1 www/templates/tab-settings.html
  190. +13 −10 www/templates/tabs.html
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -3,5 +3,16 @@

node_modules/
platforms/
platforms.bck/
plugins/
.idea
*.key
*.keystore
*.apk
icon*x*.png
build_release.sh

www/lib/*
www/fonts/*
www/dist/*
.io-config.json
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

## Catan: Simple Map Generator

This app is a lightweight generator for the Catan board game.

Features:
- Ad free
- Map generation
- Frictionless User Interface
- Various generation options
- Open source

## License

Icon build thanks to ryanschenk's work: https://www.flickr.com/photos/ryanschenk/sets/72157625243997903/detail/
Thus, icon is under Creative Common license: https://creativecommons.org/licenses/by-nc-sa/2.0/deed.en

The application sources (located in www/css, www/js, www/templates and index.html) are under the I Don't Care License: http://dev.bukkit.org/licenses/1257-i-dont-care-license/




TESTS
-----
./node_modules/.bin/appium --command-timeout 7
./node_modules/.bin/cucumber-js
18 changes: 13 additions & 5 deletions bower.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
{
"name": "myApp",
"name": "SettlersEasyMap",
"private": "true",
"devDependencies": {
"ionic": "driftyco/ionic-bower#1.0.0-beta.14"
},
"dependencies": {
"angular-local-storage": "~0.1.5"
"ionic": "driftyco/ionic-bower#1.0.0-rc.0",
"angular-local-storage": "~0.1.5",
"pixi": "~2.2.3",
"Faker": "~2.1.2",
"ionic-platform-web-client": "^0.2.1"
},
"overrides": {
"ionic-platform-web-client": {
"main": [
"./dist/ionic.io.bundle.min.js"
]
}
}
}
70 changes: 53 additions & 17 deletions config.xml
Original file line number Diff line number Diff line change
@@ -1,22 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<widget id="com.ionicframework.myapp587762" version="0.0.1" xmlns="http://www.w3.org/ns/widgets"
xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>Catan Buddy</name>
<description>
The catan bro to help you generate a map
<widget id="com.prevostc.settlerseasymap" version="1.2.7" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>Settlers: Easy Map</name>
<description>
Generate maps for The Settlers of Catan Board game
</description>
<author email="prevostclement@gmail.com" href="https://github.com/prevostc">
<author email="prevostclement@gmail.com" href="https://github.com/prevostc">
Clément Prévost
</author>
<content src="index.html"/>
<access origin="*"/>
<preference name="webviewbounce" value="false"/>
<preference name="UIWebViewBounce" value="false"/>
<preference name="DisallowOverscroll" value="true"/>
<preference name="BackupWebStorage" value="none"/>
<preference name="orientation" value="portrait"/>
<feature name="StatusBar">
<param name="ios-package" value="CDVStatusBar" onload="true"/>
</feature>
<icon src="icon.png" />
<content src="index.html"/>
<access origin="*"/>
<preference name="webviewbounce" value="false"/>
<preference name="UIWebViewBounce" value="false"/>
<preference name="DisallowOverscroll" value="true"/>
<preference name="BackupWebStorage" value="none"/>
<preference name="orientation" value="portrait"/>
<preference name="SplashScreen" value="screen"/>
<preference name="SplashScreenDelay" value="3000"/>
<feature name="StatusBar">
<param name="ios-package" value="CDVStatusBar" onload="true"/>
</feature>
<icon src="resources/android/icon/drawable-xhdpi-icon.png"/>
<platform name="android">
<icon src="resources/android/icon/drawable-ldpi-icon.png" density="ldpi"/>
<icon src="resources/android/icon/drawable-mdpi-icon.png" density="mdpi"/>
<icon src="resources/android/icon/drawable-hdpi-icon.png" density="hdpi"/>
<icon src="resources/android/icon/drawable-xhdpi-icon.png" density="xhdpi"/>
<icon src="resources/android/icon/drawable-xxhdpi-icon.png" density="xxhdpi"/>
<icon src="resources/android/icon/drawable-xxxhdpi-icon.png" density="xxxhdpi"/>
<splash src="resources/android/splash/drawable-port-ldpi-screen.png" density="port-ldpi"/>
<splash src="resources/android/splash/drawable-port-mdpi-screen.png" density="port-mdpi"/>
<splash src="resources/android/splash/drawable-port-hdpi-screen.png" density="port-hdpi"/>
<splash src="resources/android/splash/drawable-port-xhdpi-screen.png" density="port-xhdpi"/>
</platform>
<platform name="ios">
<icon src="resources/ios/icon/icon.png" width="57" height="57"/>
<icon src="resources/ios/icon/icon@2x.png" width="114" height="114"/>
<icon src="resources/ios/icon/icon-40.png" width="40" height="40"/>
<icon src="resources/ios/icon/icon-40@2x.png" width="80" height="80"/>
<icon src="resources/ios/icon/icon-50.png" width="50" height="50"/>
<icon src="resources/ios/icon/icon-50@2x.png" width="100" height="100"/>
<icon src="resources/ios/icon/icon-60.png" width="60" height="60"/>
<icon src="resources/ios/icon/icon-60@2x.png" width="120" height="120"/>
<icon src="resources/ios/icon/icon-60@3x.png" width="180" height="180"/>
<icon src="resources/ios/icon/icon-72.png" width="72" height="72"/>
<icon src="resources/ios/icon/icon-72@2x.png" width="144" height="144"/>
<icon src="resources/ios/icon/icon-76.png" width="76" height="76"/>
<icon src="resources/ios/icon/icon-76@2x.png" width="152" height="152"/>
<icon src="resources/ios/icon/icon-small.png" width="29" height="29"/>
<icon src="resources/ios/icon/icon-small@2x.png" width="58" height="58"/>
<icon src="resources/ios/icon/icon-small@3x.png" width="87" height="87"/>
<splash src="resources/ios/splash/Default-568h@2x~iphone.png" width="640" height="1136"/>
<splash src="resources/ios/splash/Default-667h.png" width="750" height="1334"/>
<splash src="resources/ios/splash/Default-Portrait~ipad.png" width="768" height="1024"/>
<splash src="resources/ios/splash/Default@2x~iphone.png" width="640" height="960"/>
<splash src="resources/ios/splash/Default~iphone.png" width="320" height="480"/>
</platform>
</widget>
14 changes: 14 additions & 0 deletions features/generate.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Feature: Generate button
Test if the generate button is present and is working as expected

Scenario: App is loaded
Given I load the app
Then I should see "Map Generator" as the page title
Then I should see "Generate" in "button.ion-shuffle"

Scenario: Generate button present
Given I load the app
Then I should see "Map Generator" as the page title
Then I click on "button.ion-shuffle"
Then I should not see "Map Generator" as the page title

15 changes: 15 additions & 0 deletions features/helpers/appium-servers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*jslint node: true */

'use strict';

exports.local = {
host: 'localhost',
port: 4723
};

exports.sauce = {
host: 'ondemand.saucelabs.com',
port: 80,
username: process.env.SAUCE_USERNAME,
password: process.env.SAUCE_ACCESS_KEY
};
7 changes: 7 additions & 0 deletions features/helpers/apps.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*jslint node: true */

'use strict';

// paths relative to appium executable directory + '/../../'
exports.android = "platforms/android/ant-build/CordovaApp-debug.apk";
exports.ios = 'platforms/ios/build/emulator/Settlers:\ Easy\ Map.app';
46 changes: 46 additions & 0 deletions features/helpers/capabilities.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*jslint node: true */

'use strict';

exports.ios = {
browserName: '',
'appium-version': '1.1',
platformName: 'iOS',
platformVersion: '8.2',
deviceName: 'iPhone 4s',
app: undefined // will be set later
};

exports.android = {
browserName: '',
'appium-version': '1.1',
platformName: 'Android',
platformVersion: '4.4',
deviceName: 'Android Emulator',
automationName: 'selendroid',
deviceType: "phone",
androidUseRunningApp: false,
app: undefined, // will be set later
};

exports.android18 = {
browserName: '',
'appium-version': '1.1',
platformName: 'Android',
platformVersion: '4.3',
deviceName: 'Android Emulator',
automationName: 'selendroid',
deviceType: "phone",
androidUseRunningApp: false,
app: undefined // will be set later
};

exports.selendroid16 = {
browserName: '',
'appium-version': '1.1',
platformName: 'Android',
platformVersion: '4.1',
automationName: 'selendroid',
deviceName: 'Android Emulator',
app: undefined // will be set later
};
18 changes: 18 additions & 0 deletions features/helpers/logging.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*jslint node: true */

'use strict';

exports.configure = function (driver) {
// See whats going on
driver.on('status', function (info) {
console.log(info.cyan);
});

driver.on('command', function (meth, path, data) {
console.log('[command] > ' + meth.yellow, path.grey, data || '');
});

driver.on('http', function (meth, path, data) {
console.log('[http] > ' + meth.magenta, path, (data || '').grey);
});
};
13 changes: 13 additions & 0 deletions features/helpers/setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
var wd = require("wd");

//require('colors');

var chai = require("chai"),
chaiAsPromised = require("chai-as-promised");

chai.use(chaiAsPromised);

var should = chai.should();
chaiAsPromised.transferPromiseness = wd.transferPromiseness;

exports.should = should;
32 changes: 32 additions & 0 deletions features/step_definition/global.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// features/step_definitions/myStepDefinitions.js

var myStepDefinitionsWrapper = function () {
this.World = require("../support/world.js").World; // overwrite default World constructor

this.Given(/^I load the app$/, function (callback) {
// nothing to do here
callback();
});

this.Then(/^I should see "([^"]*)" in "([^"]*)"$/, function (arg1, arg2, callback) {
this.driver
.waitForElementByCss(arg2, 5000)
.should.eventually.exist
.waitForElementByCss(arg2, 5000)
.text().should.eventually.include(arg1)
.notify(callback)
;
});

this.Given(/^I click on "([^"]*)"$/, function (arg1, callback) {
this.driver
.waitForElementByCss(arg1, 5000)
.should.eventually.exist
.waitForElementByCss(arg1, 5000)
.click()
.should.notify(callback)
;
});
};

module.exports = myStepDefinitionsWrapper;
31 changes: 31 additions & 0 deletions features/step_definition/ionic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// features/step_definitions/myStepDefinitions.js

var myStepDefinitionsWrapper = function () {
this.World = require("../support/world.js").World; // overwrite default World constructor

this.Then(/^I should see "([^"]*)" as the page title$/, function (arg1, callback) {
this.driver
.waitForElementByCss('div[nav-bar=active] .title.title-center', 5000)
.text().should.eventually.include(arg1)
.notify(callback)
;
});

this.Then(/^I should not see "([^"]*)" as the page title$/, function (arg1, callback) {
this.driver
.waitForElementByCss('div[nav-bar=active] .title.title-center', 5000)
.text().should.eventually.not.include(arg1)
.notify(callback)
;
});

this.Then(/^I click on the "([^"]*)" tab$/, function (arg1, callback) {
this.driver
.waitForElementByCss('ion-tabs ' + arg1, 5000)
.click()
.should.notify(callback)
;
});
};

module.exports = myStepDefinitionsWrapper;
103 changes: 103 additions & 0 deletions features/support/world.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
require('../helpers/setup');

var wd = require("wd"),
_ = require('underscore'),
serverConfigs = require('../helpers/appium-servers'),
path = require('path');

var driver;
var allPassed = true,
platform = process.env.PLATFORM || 'ios',
iOSDeviceUDID = process.env.IOS_UDID;

function setupWithAppiumServer(serverConfig) {
return wd.promiseChainRemote(serverConfig);
}

function setupLogging(driver) {
require("../helpers/logging").configure(driver);
}

function addCapabilitiesAndInit(capabilities, driver) {
var desired = _.clone(capabilities[platform]);
desired.app = path.join('../../', require("../helpers/apps")[platform]);

if (platform === 'ios' && iOSDeviceUDID) {
desired.udid = iOSDeviceUDID;
}

if (platform === 'android') {
desired.appPackage = process.env.APP_PACKAGE;
desired.appActivity = process.env.APP_ACTIVITY;
}

if (process.env.SAUCE) {
desired.name = platform + ' - Can generate';
desired.tags = ['sample'];
}
return driver.init(desired);
}

function switchToUIWebViewContext(driver) {
// instead of default NATIVE_APP context

return driver.setImplicitWaitTimeout(3000)
.contexts()
.then(function (contexts) {
var webViewContext = _.find(contexts, function (context) {
return context.indexOf('WEBVIEW') !== -1;
});
console.log('webViewContext', webViewContext);
return driver.context(webViewContext);
});
}

function beforeAll() {
var serverConfig = process.env.SAUCE ? serverConfigs.sauce : serverConfigs.local;
driver = setupWithAppiumServer(serverConfig);

// uncomment to see appium logs
//setupLogging(driver);

driver = addCapabilitiesAndInit(require("../helpers/capabilities"), driver);

return switchToUIWebViewContext(driver);
}

function afterAll() {
function sleep(time) {
var stop = new Date().getTime();
while(new Date().getTime() < stop + time) {
;
}
}
driver.quit();
console.log('Waiting for appium to quit');
sleep(7000);
}

// global setup
var envLoadedPromise = beforeAll();
process.on('beforeExit', afterAll);
//do something when app is closing
process.on('exit', afterAll);
//catches ctrl+c event
process.on('SIGINT', afterAll);
//catches uncaught exceptions
process.on('uncaughtException', afterAll);

var WorldConstructor = function WorldConstructor(callback) {

// World constructor is called for each feature

var world = {
driver: driver
};

// tell Cucumber we're finished and to use our world object instead of 'this'
envLoadedPromise.then(function() {
callback(world);
});
};
exports.World = WorldConstructor;

13 changes: 13 additions & 0 deletions features/tabs.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Feature: Tabs
Tab are present

Scenario: Settings
Given I load the app
Then I click on the ".ion-ios-gear" tab
Then I should see "Settings" as the page title

Scenario: Favorites
Given I load the app
Then I click on the ".ion-star" tab
Then I should see "Favorites" as the page title

169 changes: 134 additions & 35 deletions gulpfile.js
Original file line number Diff line number Diff line change
@@ -6,45 +6,144 @@ var sass = require('gulp-sass');
var minifyCss = require('gulp-minify-css');
var rename = require('gulp-rename');
var sh = require('shelljs');
var sourcemaps = require('gulp-sourcemaps');
var debug = require('gulp-debug');
var mainBowerFiles = require('main-bower-files');
var gulpFilter = require('gulp-filter');
var templateCache = require('gulp-angular-templatecache');
var gulpif = require('gulp-if');
var uglify = require('gulp-uglify');

var flags = {
sourceMaps: false,
uglify: true
};

var paths = {
sass: ['./scss/**/*.scss']
sass: ['./scss/**/*.scss'],
jsProject: [
"./www/js/catan/js/catan.js",
"./www/js/catan/js/hexagon.js",
"./www/js/catan/js/map.js",
"./www/js/catan/js/tools.js",
"./www/js/catan/js/ui.js",
"./www/js/catan/js/position.js",
"./www/js/catan/js/generator/generator.js",
"./www/js/catan/js/generator/generator.land.js",
"./www/js/catan/js/generator/generator.number.js",
"./www/js/catan/js/generator/generator.harbor.js",
'./www/js/**/*.js'],
jsProjectTarget: 'project.js',
jsVendorTarget: 'vendor.js',
cssProject: ['./www/css/style.css'],
cssProjectTarget: 'project.css',
cssVendorTarget: 'vendor.css',
dist: 'www/dist',
sourceMaps: 'sourcemaps/' // relative to dist path
};

gulp.task('default', ['sass']);

gulp.task('sass', function(done) {
gulp.src('./scss/ionic.app.scss')
.pipe(sass())
.pipe(gulp.dest('./www/css/'))
.pipe(minifyCss({
keepSpecialComments: 0
}))
.pipe(rename({ extname: '.min.css' }))
.pipe(gulp.dest('./www/css/'))
.on('end', done);
});

gulp.task('watch', function() {
gulp.watch(paths.sass, ['sass']);
});

gulp.task('install', ['git-check'], function() {
return bower.commands.install()
.on('log', function(data) {
gutil.log('bower', gutil.colors.cyan(data.id), data.message);
});
});

gulp.task('git-check', function(done) {
if (!sh.which('git')) {
console.log(
' ' + gutil.colors.red('Git is not installed.'),
'\n Git, the version control system, is required to download Ionic.',
'\n Download git here:', gutil.colors.cyan('http://git-scm.com/downloads') + '.',
'\n Once git is installed, run \'' + gutil.colors.cyan('gulp install') + '\' again.'
);
process.exit(1);
}
done();
gulp.task('sass', function (done) {
gulp.src('./scss/ionic.app.scss')
//.pipe(gulpif(flags.sourceMaps, sourcemaps.init()))
.pipe(sass())
//.pipe(gulpif(flags.sourceMaps, sourcemaps.write()))
.pipe(gulpif(flags.uglify, minifyCss()))
.pipe(gulp.dest('./www/css/from_scss'))
.on('end', done);
});

gulp.task('watch', function () {
gulp.watch(paths.sass, ['sass']);
gulp.watch(paths.jsProject, ['js-concat-project']);
gulp.watch(paths.cssProject, ['css-concat-project']);
gulp.watch('www/templates/**/*.html', ['html-concat-templates']);
});

gulp.task('install', ['git-check'], function () {
return bower.commands.install()
.on('log', function (data) {
gutil.log('bower', gutil.colors.cyan(data.id), data.message);
});
});

gulp.task('git-check', function (done) {
if (!sh.which('git')) {
console.log(
' ' + gutil.colors.red('Git is not installed.'),
'\n Git, the version control system, is required to download Ionic.',
'\n Download git here:', gutil.colors.cyan('http://git-scm.com/downloads') + '.',
'\n Once git is installed, run \'' + gutil.colors.cyan('gulp install') + '\' again.'
);
process.exit(1);
}
done();
});


gulp.task('build', function() {
gulp.start('sass');
gulp.start('js-concat-project');
gulp.start('js-concat-vendor');
gulp.start('css-concat-project');
gulp.start('css-concat-vendor');
gulp.start('fonts-concat-vendor');
gulp.start('html-concat-templates');
});


gulp.task('js-concat-project', function () {
return gulp.src(paths.jsProject)
.pipe(gulpif(flags.sourceMaps, sourcemaps.init()))
.pipe(concat(paths.jsProjectTarget))
.pipe(gulpif(flags.uglify, uglify()))
.pipe(gulpif(flags.sourceMaps, sourcemaps.write(paths.sourceMaps)))
.pipe(gulp.dest(paths.dist));
});

gulp.task('js-concat-vendor', function () {
return gulp.src(mainBowerFiles())
.pipe(gulpFilter('**/*.js'))
.pipe(gulpif(flags.sourceMaps, sourcemaps.init()))
.pipe(concat(paths.jsVendorTarget))
.pipe(gulpif(flags.uglify, uglify()))
.pipe(gulpif(flags.sourceMaps, sourcemaps.write(paths.sourceMaps)))
.pipe(gulp.dest(paths.dist));
});

gulp.task('css-concat-project', function () {
return gulp.src(paths.cssProject)
.pipe(gulpif(flags.sourceMaps, sourcemaps.init()))
.pipe(concat(paths.cssProjectTarget))
.pipe(gulpif(flags.uglify, minifyCss()))
.pipe(gulpif(flags.sourceMaps, sourcemaps.write(paths.sourceMaps)))
.pipe(gulp.dest(paths.dist));
});

gulp.task('css-concat-vendor', function () {
return gulp.src(mainBowerFiles())
.pipe(gulpFilter('**/*.css'))
.pipe(gulpif(flags.sourceMaps, sourcemaps.init()))
.pipe(concat(paths.cssVendorTarget))
.pipe(gulpif(flags.uglify, minifyCss()))
.pipe(gulpif(flags.sourceMaps, sourcemaps.write(paths.sourceMaps)))
.pipe(gulp.dest(paths.dist));
});

gulp.task('fonts-concat-vendor', function () {
return gulp.src(mainBowerFiles())
.pipe(gulpFilter(function (file) {
return /ionic\/fonts/.test(file.path);
}))
.pipe(gulp.dest('./www/fonts/'));
});

gulp.task('html-concat-templates', function() {
gulp.src('www/templates/**/*.html')
.pipe(templateCache({
module:'templatescache', standalone: true, root: './templates/'
}))
.pipe(gulpif(flags.uglify, uglify()))
.pipe(gulp.dest('www/dist/'));
});
Empty file modified hooks/README.md
100644 → 100755
Empty file.
28 changes: 28 additions & 0 deletions hooks/after_prepare/020_remove_sass_from_platforms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env node

/**
* After prepare, files are copied to the platforms/ios and platforms/android folders.
* Lets clean up some of those files that arent needed with this hook.
*/
var fs = require('fs');
var path = require('path');

var deleteFolderRecursive = function(removePath) {
if( fs.existsSync(removePath) ) {
fs.readdirSync(removePath).forEach(function(file,index){
var curPath = path.join(removePath, file);
if(fs.lstatSync(curPath).isDirectory()) { // recurse
deleteFolderRecursive(curPath);
} else { // delete file
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(removePath);
}
};

var iosPlatformsDir = path.resolve(__dirname, '../../platforms/ios/www/lib/ionic/scss');
var androidPlatformsDir = path.resolve(__dirname, '../../platforms/android/assets/www/lib/ionic/scss');

deleteFolderRecursive(iosPlatformsDir);
deleteFolderRecursive(androidPlatformsDir);
34 changes: 34 additions & 0 deletions hooks/after_prepare/025_remove_non_dist_from_platforms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env node

/**
* After prepare, files are copied to the platforms/ios and platforms/android folders.
* Lets clean up some of those files that arent needed with this hook.
*/
var fs = require('fs');
var path = require('path');

var deleteFolderRecursive = function(removePath) {
if( fs.existsSync(removePath) ) {
fs.readdirSync(removePath).forEach(function(file,index){
var curPath = path.join(removePath, file);
if(fs.lstatSync(curPath).isDirectory()) { // recurse
deleteFolderRecursive(curPath);
} else { // delete file
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(removePath);
}
};

var wwwPrefixes = [
'../../platforms/ios/www',
'../../platforms/android/assets/www'
];

for (var i = 0 ; i < wwwPrefixes.length ; i++) {
deleteFolderRecursive(path.resolve(__dirname, wwwPrefixes[i] + '/lib'));
deleteFolderRecursive(path.resolve(__dirname, wwwPrefixes[i] + '/js'));
deleteFolderRecursive(path.resolve(__dirname, wwwPrefixes[i] + '/css'));
deleteFolderRecursive(path.resolve(__dirname, wwwPrefixes[i] + '/dist/sourcemaps'));
}
23 changes: 23 additions & 0 deletions hooks/before_platform_add/init_directories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env node

/**
* On a fresh clone, the local platforms/ and plugins/ directories will be
* missing, so ensure they get created before the first platform is added.
*/
var fs = require('fs');
var path = require('path');

var platformsDir = path.resolve(__dirname, '../../platforms');
var pluginsDir = path.resolve(__dirname, '../../plugins');

try {
fs.mkdirSync(platformsDir, function (err) {
if (err) { console.error(err); }
});
} catch(ex) {}

try {
fs.mkdirSync(pluginsDir, function (err) {
if (err) { console.error(err); }
});
} catch(ex) {}
72 changes: 72 additions & 0 deletions hooks/before_prepare/02_jshint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env node

var fs = require('fs');
var path = require('path');
var jshint = require('jshint').JSHINT;
var async = require('async');

var foldersToProcess = [
'js'
];

foldersToProcess.forEach(function(folder) {
processFiles("www/" + folder);
});

function processFiles(dir, callback) {
var errorCount = 0;
fs.readdir(dir, function(err, list) {
if (err) {
console.log('processFiles err: ' + err);
return;
}
async.eachSeries(list, function(file, innercallback) {
file = dir + '/' + file;
fs.stat(file, function(err, stat) {
if(!stat.isDirectory()) {
if(path.extname(file) === ".js") {
lintFile(file, function(hasError) {
if(hasError) {
errorCount++;
}
innercallback();
});
} else {
innercallback();
}
} else {
innercallback();
}
});
}, function(error) {
if(errorCount > 0) {
process.exit(1);
}
});
});
}

function lintFile(file, callback) {
console.log("Linting " + file);
fs.readFile(file, function(err, data) {
if(err) {
console.log('Error: ' + err);
return;
}
if(jshint(data.toString())) {
console.log('File ' + file + ' has no errors.');
console.log('-----------------------------------------');
callback(false);
} else {
console.log('Errors in file ' + file);
var out = jshint.data(),
errors = out.errors;
for(var j = 0; j < errors.length; j++) {
console.log(errors[j].line + ':' + errors[j].character + ' -> ' + errors[j].reason + ' -> ' +
errors[j].evidence);
}
console.log('-----------------------------------------');
callback(true);
}
});
}
9 changes: 9 additions & 0 deletions hooks/before_prepare/15_run_gulp_build_tasks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env node

console.log('Building project dist');
var gulp = require('gulp');
var path = require('path');

require(path.resolve(__dirname, '../../gulpfile.js'));

gulp.start('build');
Binary file modified icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added icons.xcf
Binary file not shown.
9 changes: 6 additions & 3 deletions ionic.project
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"name": "myApp",
"app_id": ""
}
"name": "SettlersEasyMap",
"app_id": "4711f544",
"gulpStartupTasks": [
"build"
]
}
41 changes: 32 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,40 @@
{
"name": "myapp",
"name": "SettlersEasyMap",
"version": "1.0.0",
"description": "myApp: An Ionic project",
"description": "SettlersEasyMap: An Ionic project",
"dependencies": {
"gulp": "^3.5.6",
"gulp-sass": "^0.7.1",
"gulp-concat": "^2.2.0",
"gulp-minify-css": "^0.3.0",
"gulp-rename": "^1.2.0"
"chai": "^2.2.0",
"chai-as-promised": "^4.3.0",
"colors": "^1.0.3",
"cucumber": "^0.4.8",
"gulp-if": "^1.2.5",
"gulp-uglify": "^1.1.0",
"underscore": "^1.8.2"
},
"devDependencies": {
"async": "^0.9.0",
"bower": "^1.3.3",
"cordova-minify": "0.0.12",
"gulp": "^3.5.6",
"gulp-angular-templatecache": "^1.5.0",
"gulp-concat": "^2.2.0",
"gulp-concat-vendor": "0.0.4",
"gulp-debug": "~2.0.1",
"gulp-filter": "~2.0.2",
"gulp-minify-css": "^0.3.0",
"gulp-rename": "^1.2.0",
"gulp-sass": "^0.7.1",
"gulp-sourcemaps": "~1.5.0",
"gulp-util": "^2.2.14",
"jshint": "^2.6.3",
"main-bower-files": "~2.5.0",
"shelljs": "^0.3.0"
}
}
},
"cordovaPlugins": [
"org.apache.cordova.device"
],
"cordovaPlatforms": [
"android",
"ios"
]
}
Binary file added resources/android/icon/drawable-hdpi-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/android/icon/drawable-ldpi-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/android/icon/drawable-mdpi-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/android/icon/drawable-xhdpi-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/android/icon/drawable-xxhdpi-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/android/icon/drawable-xxxhdpi-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/ios/icon/icon-40.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/ios/icon/icon-50.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/ios/icon/icon-60.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/ios/icon/icon-72.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/ios/icon/icon-76.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/ios/icon/icon-small.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/ios/icon/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/ios/splash/Default-568h@2x~iphone.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/ios/splash/Default-667h.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/ios/splash/Default-Portrait~ipad.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/ios/splash/Default@2x~iphone.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/ios/splash/Default~iphone.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/splash.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 39 additions & 0 deletions www/css/style.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,43 @@
/* Empty. Add your own CSS if you like */
.canvas-container {
height: 100%;
}

.my-image-item{
left: 0;
right: 0;
}

.my-image-item img {
height: 100%;
}

.item-avatar.my-image-item img {
max-width: 150px;
max-height: 150px;
}

.list .item:first-child{
border-top: none;
}

.list .item:last-child {
border-bottom: none;
}


.ion-ios-star.favorite-button, .ion-ios-star.favorite-button:focus, .ion-ios-star.favorite-button:hover {
color: rgb(255, 206, 52);
}

.home.spacer{
height: 1000px;
}

.item .item-content {
padding-right: 5px;
}
.item .item-content.activated {
border-right: 3px solid #ccc;
background-color: #fff;
}
Binary file added www/img/desert.png
Binary file added www/img/empty.png
Binary file added www/img/field.png
Binary file added www/img/forest.png
Binary file added www/img/hills.png
Binary file added www/img/mountain.png
Binary file added www/img/number.png
Binary file added www/img/ocean.png
Binary file added www/img/pasture.png
34 changes: 9 additions & 25 deletions www/index.html
Original file line number Diff line number Diff line change
@@ -3,36 +3,20 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title></title>
<title>Settlers: Easy Map</title>
<link href="dist/vendor.css" rel="stylesheet">
<link href="dist/project.css" rel="stylesheet">

<link href="lib/ionic/css/ionic.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">

<!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above
<link href="css/ionic.app.css" rel="stylesheet">
-->

<!-- ionic/angularjs js -->
<script src="lib/ionic/js/ionic.bundle.js"></script>
<!-- ionic/angularjs js -->
<script src="lib/angular-local-storage/dist/angular-local-storage.min.js"></script>

<!-- catan/catan js -->
<script src="js/catan/js/catan.js"></script>
<script src="js/catan/js/hexagon.js"></script>
<script src="js/catan/js/map.js"></script>
<script src="js/catan/js/tools.js"></script>
<script src="js/catan/js/ui.js"></script>
<script src="js/catan/js/position.js"></script>
<script src="dist/vendor.js"></script>

<!-- cordova script (this will be a 404 during development) -->
<script src="cordova.js"></script>
<!-- Cordova is bootstrapped by ionic-platform-web-client, uncomment this if you remove ionic-platform-web-client... -->
<!-- <script src="cordova.js"></script> -->

<!-- your app's js -->
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
<script src="js/services.js"></script>
</head>
<script src="dist/templates.js"></script>
<script src="dist/project.js"></script>

<body ng-app="starter">
<!--
The nav bar that will be updated as we navigate between views.
141 changes: 87 additions & 54 deletions www/js/app.js
Original file line number Diff line number Diff line change
@@ -1,64 +1,97 @@
// Ionic Starter App
//noinspection JSHint
(function (angular) {
"use strict";

// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
// 'starter.services' is found in services.js
// 'starter.controllers' is found in controllers.js
angular.module('starter', ['ionic', 'starter.controllers', 'starter.services'])
// Ionic Starter App

.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
});
})
// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
// 'starter.services' is found in services.js
// 'starter.controllers' is found in controllers.js
angular.module('starter', ['ionic','ionic.service.core', 'ionic.service.analytics', 'starter.controllers', 'starter.services', 'templatescache'])

.config(function($stateProvider, $urlRouterProvider) {
.run(['$ionicPlatform', '$ionicAnalytics', '$window', function ($ionicPlatform, $ionicAnalytics, $window) {
$ionicPlatform.ready(function () {
$ionicAnalytics.register();
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if ($window.cordova && $window.cordova.plugins && $window.cordova.plugins.Keyboard) {
$window.cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if ($window.StatusBar) {
// org.apache.cordova.statusbar required
$window.StatusBar.styleDefault();
}
});
}])

// Ionic uses AngularUI Router which uses the concept of states
// Learn more here: https://github.com/angular-ui/ui-router
// Set up the various states which the app can be in.
// Each state's controller can be found in controllers.js
$stateProvider
.config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {

// setup an abstract state for the tabs directive
.state('tab', {
url: "/tab",
abstract: true,
templateUrl: "templates/tabs.html"
})
// Ionic uses AngularUI Router which uses the concept of states
// Learn more here: https://github.com/angular-ui/ui-router
// Set up the various states which the app can be in.
// Each state's controller can be found in controllers.js
$stateProvider

// Each tab has its own nav history stack:
// setup an abstract state for the tabs directive
.state('tab', {
url: "/tab",
abstract: true,
templateUrl: "templates/tabs.html"
})

.state('tab.map', {
url: '/map',
views: {
'tab-map': {
templateUrl: 'templates/tab-map.html',
controller: 'MapCtrl'
}
}
})
// Each tab has its own nav history stack:
.state('tab.map', {
url: '/map',
views: {
'tab-map': {
templateUrl: 'templates/tab-map.html',
controller: 'MapCtrl'
}
}
})

.state('tab.settings', {
url: '/settings',
views: {
'tab-settings': {
templateUrl: 'templates/tab-settings.html',
controller: 'SettingsCtrl'
}
}
});
.state('tab.settings', {
url: '/settings',
views: {
'tab-settings': {
templateUrl: 'templates/tab-settings.html',
controller: 'SettingsCtrl'
}
}
})

// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/tab/map');
.state('tab.favorites', {
url: '/favorites',
views: {
'tab-favorites': {
templateUrl: 'templates/tab-favorites.html',
controller: 'FavoritesCtrl'
}
}
})

});
// Each tab has its own nav history stack:
.state('tab.favorites-view', {
url: '/favorites/:mapData',
views: {
'tab-favorites': {
templateUrl: 'templates/tab-favorites-view.html',
controller: 'FavoritesViewCtrl'
}
},
resolve: {
mapData: ['$stateParams', 'Favorites', function ($stateParams, Favorites) {
return Favorites.fetchById($stateParams.mapData);
}]
}
})
;

// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/tab/map');

}]);

})(angular);
11 changes: 10 additions & 1 deletion www/js/catan/js/Position.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//noinspection JSHint
(function (Catan) {
"use strict";

@@ -6,7 +7,15 @@
this.line = line;

// Make the position immutable
//Object.freeze(this);
Object.freeze(this);
};

Catan.Position.serialize = function(position) {
return position;
};

Catan.Position.unserialize = function(serializedPosition) {
return new Catan.Position(serializedPosition.column, serializedPosition.line);
};

})(Catan);
26 changes: 1 addition & 25 deletions www/js/catan/js/catan.js
Original file line number Diff line number Diff line change
@@ -3,8 +3,6 @@ Catan = (function () {
"use strict";

var Catan = {
debug: false,

T: {
Hills: 1,
Pasture: 2,
@@ -13,31 +11,9 @@ Catan = (function () {
Forest: 5,
Desert: 6,
Ocean: 7,
Harbor: 8,
Empty: 9
Empty: 8
}
};


Catan.generateMap = function (canvas, tileTrioScoreLimit) {
tileTrioScoreLimit = tileTrioScoreLimit || 12;

var terrains, res, map;

do {
map = new Catan.Map(7, 7, new Catan.Position(3, 3));
do {
terrains = map.generateTerrains();
} while (terrains.length > 0);

res = map.generateNumbers(tileTrioScoreLimit);
} while (!res);

map.generateHarbors();

Catan.UI.drawMap(map, canvas);
return map;
};

return Catan;
})();
111 changes: 111 additions & 0 deletions www/js/catan/js/generator/generator.harbor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
//noinspection JSHint
(function(Catan) {
"use strict";

Catan.Generator.Harbor = {};

Catan.Generator.Harbor.generate = function (map) {
var mod = Math.round(Math.random());
var n = 0;

// create harbors
var landHarbors = [
Catan.T.Hills, Catan.T.Forest,
Catan.T.Fields, Catan.T.Mountains, Catan.T.Pasture
];
Catan.Tools.shuffle(landHarbors);
var empties = [Catan.T.Empty, Catan.T.Empty, Catan.T.Empty, Catan.T.Empty];
var harbors = [];
for (var i = empties.length; i > 0; --i) {
harbors.push(landHarbors.pop());
harbors.push(empties.pop());
}
harbors.push(landHarbors.pop());
Catan.Tools.rotate(harbors, (Catan.Tools.randInterval(0, harbors.length - 1)));

var harborCoords = [];

// put harbors on map and index
map.eachCoast(function (i, j) {
// set oceans and harbors
if (n++ % 2 === mod) {
map.get(i, j).land = harbors.pop();

if (map.get(i, j).land !== Catan.T.Empty) {
harborCoords.push(new Catan.Position(i, j));
}
} else {
map.get(i, j).land = Catan.T.Ocean;
}
});

var lands = [
Catan.T.Hills,
Catan.T.Pasture,
Catan.T.Mountains,
Catan.T.Fields,
Catan.T.Forest,
Catan.T.Desert
];

// swap harbors
var swapped = true;
for (var limit = 0; swapped && limit < 30; limit++) {
swapped = false;
Catan.Tools.shuffle(harborCoords);
for (var h = 0; h < harborCoords.length; h++) {
var currentHarbor = map.get(harborCoords[h].column, harborCoords[h].line);
var allowedLands = lands;
allowedLands = map.getAllowedLands(harborCoords[h].column, harborCoords[h].line, allowedLands);

if (!Catan.Tools.contains(allowedLands, currentHarbor.land)) {
// find a place to go
for (var hh = 0; hh < harborCoords.length; hh++) {
allowedLands = lands;
allowedLands = map.getAllowedLands(harborCoords[hh].column, harborCoords[hh].line, allowedLands);
if (Catan.Tools.contains(allowedLands, currentHarbor.land)) {
// do swap
var swapHarbor = map.get(harborCoords[hh].column, harborCoords[hh].line);
var cTmp = swapHarbor.land;
swapHarbor.land = currentHarbor.land;
currentHarbor.land = cTmp;
swapped = true;
}
}
}
}
}
};


Catan.Generator.Harbor.generateCoastBars = function (map) {
var coastBarsOrderedClockwiseType1 = [
[Catan.T.Empty, Catan.T.Ocean, Catan.T.Hills],
[Catan.T.Empty, Catan.T.Ocean, Catan.T.Pasture],
[Catan.T.Empty, Catan.T.Ocean, Catan.T.Fields]
];
var coastBarsOrderedClockwiseType2 = [
[Catan.T.Ocean, Catan.T.Empty, Catan.T.Ocean],
[Catan.T.Ocean, Catan.T.Forest, Catan.T.Ocean],
[Catan.T.Ocean, Catan.T.Mountains, Catan.T.Ocean]
];

Catan.Tools.shuffle(coastBarsOrderedClockwiseType1);
Catan.Tools.shuffle(coastBarsOrderedClockwiseType2);

var coastLandTypesOrderedClockwise = [];
var randomCoastBarType = Math.round(Math.random() * 100);
for (var i = 0 ; i < 6 ; i++) {
var harborBars = (i + randomCoastBarType) % 2 ? coastBarsOrderedClockwiseType1 : coastBarsOrderedClockwiseType2;
var harborBar = harborBars.pop();
coastLandTypesOrderedClockwise.push(harborBar.pop());
coastLandTypesOrderedClockwise.push(harborBar.pop());
coastLandTypesOrderedClockwise.push(harborBar.pop());
}

map.eachCoast(function (column, line) {
var harbor = map.get(column, line);
harbor.land = coastLandTypesOrderedClockwise.pop();
});
};
})(Catan);
31 changes: 31 additions & 0 deletions www/js/catan/js/generator/generator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//noinspection JSHint
(function(Catan) {
"use strict";

Catan.Generator = {};

Catan.Generator.Map = {};

Catan.Generator.Map.generate = function (tileTrioScoreLimit, harborGenerationStrategyName) {
tileTrioScoreLimit = tileTrioScoreLimit || 12;

var lands, res, map;

do {
map = new Catan.Map(7, 7, new Catan.Position(3, 3));
do {
lands = Catan.Generator.Land.generate(map);
} while (lands.length > 0);

res = Catan.Generator.Number.generate(map, tileTrioScoreLimit);
} while (!res);

if (harborGenerationStrategyName === 'coast-bars') {
Catan.Generator.Harbor.generateCoastBars(map);
} else {
Catan.Generator.Harbor.generate(map);
}
return map;
};

})(Catan);
92 changes: 92 additions & 0 deletions www/js/catan/js/generator/generator.land.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//noinspection JSHint
(function(Catan) {
"use strict";

Catan.Generator.Land = {};

Catan.Generator.Land.generate = function (map) {
var allowedLands;
// init map with random lands
var lands = [
Catan.T.Hills, Catan.T.Hills, Catan.T.Hills,
Catan.T.Pasture, Catan.T.Pasture, Catan.T.Pasture, Catan.T.Pasture,
Catan.T.Mountains, Catan.T.Mountains, Catan.T.Mountains,
Catan.T.Fields, Catan.T.Fields, Catan.T.Fields, Catan.T.Fields,
Catan.T.Forest, Catan.T.Forest, Catan.T.Forest, Catan.T.Forest,
Catan.T.Desert
];

Catan.Tools.shuffle(lands);
map.each(function (i, j) {
map.get(i, j).land = lands.pop();
});

// unset same lands neighbours
var emptySpots = [];
map.each(function (i, j) {
var a;
var b;
map.eachConsecutiveNeighbour(i, j, function (a, b) {
return (a.land === b.land && a.land !== Catan.T.Empty && a.land !== undefined);
}, function (ax, ay, bx, by) {
a = map.get(ax, ay);
b = map.get(bx, by);
lands.push(a.land);
a.land = undefined;
emptySpots.push(a.position);
});
});

// repush as much lands as possible
var newEmptySpots = [];
Catan.Tools.shuffle(emptySpots);
Catan.Tools.shuffle(lands);

for (var i = 0; i < emptySpots.length; ++i) {
allowedLands = map.getAllowedLands(emptySpots[i].column, emptySpots[i].line, lands);

if (allowedLands.length > 0) {
map.get(emptySpots[i].column, emptySpots[i].line).land = allowedLands[0];
lands = Catan.Tools.removeOne(lands, allowedLands[0]);
} else {
newEmptySpots.push(emptySpots[i]);
}
}
emptySpots = newEmptySpots;

// swap as much as possible
var allLands;
var swapped = false;
var eachSwapFunction = function (i, j) {
if (!swapped && !(i === ex && j === ey) && Catan.Tools.contains(allowedLands, map.get(i, j).land)) {
var currentAllowedLands = map.getAllowedLands(i, j, allLands);
for (var t = 0; t < lands.length && !swapped; t++) {
if (map.get(i, j).land !== lands[t] && Catan.Tools.contains(currentAllowedLands, lands[t])) {
// set empty spot land to current.land
map.get(ex, ey).land = map.get(i, j).land;
// set current land to land[t]
map.get(i, j).land = lands[t];
// remove land[t] from land
lands = Catan.Tools.removeOne(lands, lands[t]);
// set item swapped
swapped = true;
}
}
}
};

for (var cur = 0; cur < emptySpots.length; ++cur) {
var ex = emptySpots[cur].column;
var ey = emptySpots[cur].line;
allLands = [Catan.T.Hills, Catan.T.Pasture, Catan.T.Mountains, Catan.T.Fields, Catan.T.Forest, Catan.T.Desert];
allowedLands = map.getAllowedLands(ex, ey, allLands);
// if smth is allowed
if (allowedLands.length > 0) {
swapped = false;
map.each(eachSwapFunction);
}
}

return lands;
};
})(Catan);
173 changes: 173 additions & 0 deletions www/js/catan/js/generator/generator.number.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
//noinspection JSHint
(function(Catan) {
"use strict";

Catan.Generator.Number = {};

Catan.Generator.Number.generate = function (map, tileTrioScoreLimit) {
var i, j;
var numbers = [11, 12, 9, 4, 6, 5, 10, 3, 11, 4, 8, 8, 10, 9, 3, 5, 2, 6];
// sort tdsc DESC
Catan.Tools.shuffle(numbers);
numbers.sort(function (a, b) {
return Catan.Tools.tdsc(b) - Catan.Tools.tdsc(a);
});

// group numbers in 5 groups, 3 groups of 4 numbers, 2 groups of 3 numbers
// the tdsc sum of each group should be as close as possible
var groups = {};
groups[Catan.T.Hills] = {size: 3, numbers: [], pos: []};
groups[Catan.T.Pasture] = {size: 4, numbers: [], pos: []};
groups[Catan.T.Mountains] = {size: 3, numbers: [], pos: []};
groups[Catan.T.Fields] = {size: 4, numbers: [], pos: []};
groups[Catan.T.Forest] = {size: 4, numbers: [], pos: []};
var groupKeys = [Catan.T.Hills, Catan.T.Pasture, Catan.T.Mountains, Catan.T.Fields, Catan.T.Forest];

// fill groups
for (i = 0; i < numbers.length; ++i) {
// add some rand (in case of lowest equality)
Catan.Tools.shuffle(groupKeys);
// look for the lowest tdsc sum
var lowest;
for (j = 0; j < groupKeys.length; j++) {
// continue when size reached
if (groups[groupKeys[j]].numbers.length === groups[groupKeys[j]].size) {
continue;
}
// init lowest
if (lowest === undefined) {
lowest = groups[groupKeys[j]];
continue;
}
// update lowest
if (Catan.Tools.tdscSum(lowest.numbers) > Catan.Tools.tdscSum(groups[groupKeys[j]].numbers)) {
lowest = groups[groupKeys[j]];
}
}
lowest.numbers.push(numbers[i]);
}

// put the numbers in the map
// and index lands groups
map.each(function (i, j) {
var current = map.get(i, j);
if (current.land !== Catan.T.Desert) {
current.number = groups[current.land].numbers.pop();
groups[current.land].pos.push({x: i, y: j});
}
});

// define swap function (eye candy)
var swapNumber = function (current, maxTdsc, maxNeighbourTdsc) {
// swap current number with one in the same land group
// choose the square with the lowest max(neighbour.number)
// that make the sum goes below the limit
var getMax = function (i, j) {
var max = -1;
var neighbour;
map.eachNeighbour(i, j, function (x, y) {
neighbour = map.get(x, y);
if (neighbour.number !== undefined && Catan.Tools.tdsc(neighbour.number) > max) {
max = neighbour.number;
}
});
return max;
};

// find the land to swap number with
var min;
var minCoord;
var max;
for (var c = 0; c < groups[current.land].pos.length; ++c) {
var coord = groups[current.land].pos[c];
if (Catan.Tools.tdsc(map.get(coord.x, coord.y).number) < maxTdsc) {
max = getMax(coord.x, coord.y);
if (max !== undefined) {
//noinspection JSUnusedAssignment
if (min === undefined || max < min) {
min = max;
minCoord = coord;
}
}
}
}

// do the swap
if (minCoord !== undefined) {
var n = current.number;
current.number = map.get(minCoord.x, minCoord.y).number;
map.get(minCoord.x, minCoord.y).number = n;
}
};

// do swap if > limit
var coordinates = [];
var eachPushCoordinatesFunction = function (i, j) {
coordinates.push(new Catan.Position(i, j));
};
var isCoupleValidFunction = function (a, b) {
return (a.land != Catan.T.Empty && b.land !== Catan.T.Empty && a.number !== undefined && b.number !== undefined);
};
var doSwapFunction = function (ax, ay, bx, by) {
a = map.get(ax, ay);
b = map.get(bx, by);

// when current trio sum is > trioLimit
if (trioLimit < Catan.Tools.tdsc(a.number) + Catan.Tools.tdsc(b.number) + Catan.Tools.tdsc(current.number)) {
overTrioLimit = true;
swapNumber(current, trioLimit - ( Catan.Tools.tdsc(a.number) + Catan.Tools.tdsc(b.number)));
}

// when current and neighbour are > duoLimit
if ((duoLimit < Catan.Tools.tdsc(a.number) + Catan.Tools.tdsc(current.number)) || (duoLimit < Catan.Tools.tdsc(b.number) + Catan.Tools.tdsc(current.number))) {
overDuoLimit = true;
// swap with a neighbour without a neighbour set to 5 tdsc
swapNumber(
current,
trioLimit - (Catan.Tools.tdsc(a.number) + Catan.Tools.tdsc(b.number)),
duoLimit - Catan.Tools.tdsc(current.number)
);
}
};
var overTrioLimit = true;
var overDuoLimit = true;
var missingLandNumber = true;

var isLandNumberMissing = function(col, line) {
var hexagon = map.get(col, line);

// test if a number is missing
if (hexagon.isLand() && !hexagon.isHarbor() && !hexagon.isCoast() && hexagon.land !== 6 && hexagon.number === undefined) {
missingLandNumber = true;
}
};
for (var maxRepeat = 0; missingLandNumber && overTrioLimit && overDuoLimit && maxRepeat < 100; maxRepeat++) {
overTrioLimit = false;
overDuoLimit = false;
missingLandNumber = false;

// add some entropy
coordinates = [];
map.each(eachPushCoordinatesFunction);
Catan.Tools.shuffle(coordinates);

for (var c = 0; c < coordinates.length; ++c) {
i = coordinates[c].column;
j = coordinates[c].line;
var current = map.get(i, j);
var a, b;
var trioLimit = tileTrioScoreLimit;
var duoLimit = 9;
// avoid desert
if (current.number !== undefined) {
map.eachConsecutiveNeighbour(i, j, isCoupleValidFunction, doSwapFunction);
}
}

map.each(isLandNumberMissing);
}

// test if all trio are below the limit
return !(overTrioLimit || overDuoLimit || missingLandNumber);
};
})(Catan);
76 changes: 69 additions & 7 deletions www/js/catan/js/hexagon.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,79 @@
//noinspection JSHint
(function(Catan) {
"use strict";

// 2 3 4 5 6 7 8 9 10 11 12
// 1 2 3 4 5 6 5 4 3 2 1
Catan.Hexagon = function (terrain, pos) {
this.terrain = terrain;
// 2 3 4 5 6 7 8 9 10 11 12
// 1 2 3 4 5 6 5 4 3 2 1
Catan.Hexagon = function (pos, land) {
this.position = pos;
this.number = undefined;
this.circle = undefined;
this.land = land;
};

Catan.Hexagon.serialize = function(hexagon) {
hexagon.type = hexagon.getType();
return hexagon;
};
Catan.Hexagon.unserialize = function(hexagon) {
if (hexagon.type === "Hexagon") {
return new Catan.Hexagon(Catan.Position.unserialize(hexagon.position), hexagon.land);
}
var constructor = Catan.Hexagon[hexagon.type];
var unserializedHexagon = new constructor(Catan.Position.unserialize(hexagon.position), hexagon.land);
unserializedHexagon.number = hexagon.number;
return unserializedHexagon;
};

Catan.Hexagon.prototype.getType = function () {
return "Hexagon";
};
Catan.Hexagon.prototype.isEmpty = function () {
return this.terrain == Catan.T.Empty;
return this.land === Catan.T.Empty;
};
Catan.Hexagon.prototype.isCoast = function () {
return false;
};
Catan.Hexagon.prototype.isHarbor = function () {
return false;
};
Catan.Hexagon.prototype.isLand = function () {
return false;
};
Catan.Hexagon.prototype.hasNumber = function () {
return false;
};



Catan.Hexagon.Land = function (pos, land) {
Catan.Hexagon.call(this, pos, land);
this.number = undefined;
};
Catan.Hexagon.Land.prototype = new Catan.Hexagon();

Catan.Hexagon.Land.prototype.getType = function () {
return "Land";
};
Catan.Hexagon.Land.prototype.isLand = function () {
return true;
};
Catan.Hexagon.Land.prototype.hasNumber = function () {
return this.number !== undefined;
};


Catan.Hexagon.Coast = function (pos, land) {
Catan.Hexagon.call(this, pos, land);
};
Catan.Hexagon.Coast.prototype = new Catan.Hexagon();

Catan.Hexagon.Coast.prototype.getType = function () {
return "Coast";
};
Catan.Hexagon.Coast.prototype.isCoast = function () {
return true;
};
Catan.Hexagon.Coast.prototype.isHarbor = function () {
return this.land !== Catan.T.Ocean;
};

})(Catan);
422 changes: 73 additions & 349 deletions www/js/catan/js/map.js

Large diffs are not rendered by default.

17 changes: 12 additions & 5 deletions www/js/catan/js/tools.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//noinspection JSHint
(function(Catan){
"use strict";

@@ -16,8 +17,10 @@
Catan.Tools.removeOne = function (a, o) {
var removed = false;
return a.filter(function (element, index, array) {
if (removed) return true;
if (element == o) {
if (removed) {
return true;
}
if (element === o) {
removed = true;
return false;
}
@@ -41,13 +44,17 @@
return sum;
};

Catan.Tools.rotate = function (a, inc) {
Catan.Tools.rotate = function (a, inc)
{
var l = a.length, i, x;
inc = Math.abs(inc) >= l && (inc %= l) ||
inc < 0 && (inc += l) ||
inc;
for (; inc; inc = (Math.ceil(l / inc) - 1) * inc - l + (l = inc))
for (i = l; i > inc; x = a[--i], a[i] = a[i - inc], a[i - inc] = x);
for (; inc; inc = (Math.ceil(l / inc) - 1) * inc - l + (l = inc)) {
for (i = l; i > inc; x = a[--i], a[i] = a[i - inc], a[i - inc] = x) {
// nothing
}
}
};

// the number of two dice combination with a sum equal to this number
204 changes: 187 additions & 17 deletions www/js/catan/js/ui.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,153 @@
(function(Catan){
//noinspection JSHint
(function (Catan, PIXI) {
"use strict";

Catan.UI = {};
var textures = {};
var areAssetsLoaded = false;

Catan.UI.drawMap = function (map, canvas) {
Catan.UI = {
// if set to true, displays the coordinates system
debug: false
};

Catan.UI.HighDefinition = {};
Catan.UI.LowDefinition = {};

Catan.UI.HighDefinition.getBase64String = function (renderer) {
return renderer.view.toDataURL();
};

Catan.UI.HighDefinition.init = function(canvasContainer, width, height, loadedCallback) {
// You can use either PIXI.WebGLRenderer or PIXI.CanvasRenderer or PIXI.autoDetectRenderer
// set a zero height at first so that the black screen is hidden
var renderer = new PIXI.CanvasRenderer(width, height, {view: canvasContainer.childNodes[0]});

var stage = new PIXI.Stage(0xFFFFFF);
renderer.render(stage);

var assets = [
"img/field.png", "img/desert.png", "img/forest.png", "img/pasture.png",
"img/hills.png","img/mountain.png","img/ocean.png","img/empty.png", "img/number.png"
];

if (!areAssetsLoaded) {
var loader = new PIXI.AssetLoader(assets, false);
loader.onComplete = function(){
textures[Catan.T.Fields] = PIXI.Texture.fromFrame("img/field.png");
textures[Catan.T.Desert] = PIXI.Texture.fromFrame("img/desert.png");
textures[Catan.T.Forest] = PIXI.Texture.fromFrame("img/forest.png");
textures[Catan.T.Pasture] = PIXI.Texture.fromFrame("img/pasture.png");
textures[Catan.T.Hills] = PIXI.Texture.fromFrame("img/hills.png");
textures[Catan.T.Mountains] = PIXI.Texture.fromFrame("img/mountain.png");
textures[Catan.T.Ocean] = PIXI.Texture.fromFrame("img/ocean.png");
textures[Catan.T.Empty] = PIXI.Texture.fromFrame("img/empty.png");
textures.token = PIXI.Texture.fromFrame("img/number.png");
areAssetsLoaded = true;
loadedCallback(renderer);
};

loader.load();
} else {
loadedCallback(renderer);
}

return renderer;
};

Catan.UI.HighDefinition.draw = function (renderer, map, width, height) {
var stage = new PIXI.Stage(0xFFFFFF);

var tileWidth = 200,
tileHeight = 230;

var mapScale = Math.min(width/(7*tileWidth), height/((19/3)*tileHeight));

// create an empty container
var tileContainer = new PIXI.DisplayObjectContainer();

// tiles are rotated so width correspond to height
tileContainer.position.x = (width / 2) - (((9/3) * tileWidth * mapScale) / 2);
tileContainer.position.y = (height / 2) - ((8 * tileHeight * mapScale) / 2);
tileContainer.pivot.x = 0.5;
tileContainer.pivot.y = 0.5;
tileContainer.rotation = Math.PI/6;
tileContainer.scale.x = mapScale;
tileContainer.scale.y = mapScale;
var tiles = [];

stage.addChild(tileContainer);

var drawHexagonCallback = function(i, j){
var hexagon = map.get(i, j);
var cx = hexagon.position.column * tileWidth - ((hexagon.position.line + 1) % 2) * tileWidth / 2 + tileWidth / 2,
cy = hexagon.position.line * (3 / 4 * tileHeight) + tileHeight / 2;// + canvasHeight / 2 - mapHeight / 2

var tile;

if (hexagon.isCoast()) {
tile = new PIXI.Sprite(textures[Catan.T.Ocean]);
} else {
tile = new PIXI.Sprite(textures[hexagon.land]);
}

tile.position.x = cx;
tile.position.y = cy;
tile.scale.x = 1;
tile.scale.y = 1;
tile.anchor.x = 0.5;
tile.anchor.y = 0.5;
tile.rotation = - (Catan.Tools.randInterval(0,6) * 2 + 1) * Math.PI/6;
tiles.push(tile);
tileContainer.addChild(tile);

if (hexagon.isLand() && hexagon.hasNumber()) {
var token = new PIXI.Sprite(textures.token);
token.position.x = cx;
token.position.y = cy;
token.scale.x = 1.1;
token.scale.y = 1.1;
token.anchor.x = 0.5;
token.anchor.y = 0.5;
tileContainer.addChild(token);

var textSize = Catan.Tools.tdsc(hexagon.number) * 5 + 45;
var textColor = Catan.Tools.tdsc(hexagon.number) >= 5 ? 'red' : 'black';
var text = new PIXI.Text(hexagon.number, {font: textSize + "px Arial", fill:textColor});
text.position.x = cx;
text.position.y = cy;
text.anchor.x = 0.5;
text.anchor.y = 0.5;
text.rotation = -Math.PI/6;
tileContainer.addChild(text);
}


if (hexagon.isHarbor()) {
var harbor = new PIXI.Sprite(textures[hexagon.land]);
harbor.position.x = cx;
harbor.position.y = cy;
harbor.scale.x = 0.4;
harbor.scale.y = 0.4;
harbor.anchor.x = 0.5;
harbor.anchor.y = 0.5;
harbor.rotation = - (Catan.Tools.randInterval(0,6) * 2 + 1) * Math.PI/6;
tileContainer.addChild(harbor);
}
};

map.each(drawHexagonCallback);
map.eachCoast(drawHexagonCallback);

renderer.render(stage);
};



Catan.UI.LowDefinition.getBase64String = function (canvas) {
return canvas.toDataURL();
};

Catan.UI.LowDefinition.drawMap = function (map, canvas) {
var ctx = canvas.getContext('2d');

// align numbers
@@ -21,21 +165,22 @@
// reset canvas
//noinspection SillyAssignmentJS
canvas.width = canvas.width;
ctx.clearRect (0, 0, canvas.width, canvas.height);
ctx.fillStyle="white";
ctx.fillRect(0, 0, canvas.width, canvas.height);

for (var i = 0; i < map.board.length; i++) {
for (var j = 0; j < map.board[i].length; j++) {
if (map.get(i, j).terrain != Catan.T.Empty) {
Catan.UI.drawHexagon(map.get(i, j), ctx, size, dist);
}
Catan.UI.LowDefinition.drawHexagon(map.get(i, j), ctx, size, dist);
}
}
};

Catan.UI.drawHexagon = function (hexagon, ctx, size, dist) {
Catan.UI.LowDefinition.drawHexagon = function (hexagon, ctx, size, dist) {

var getColorFromTerrain = function (terrain) {
var getColorFromLand = function (land) {
var color;
switch (terrain) {
switch (land) {
case Catan.T.Hills:
color = "rgb(224, 129, 27)";
break;
@@ -54,13 +199,37 @@
case Catan.T.Desert:
color = "rgb(255, 255, 117)";
break;
case Catan.T.Harbor:
case Catan.T.Ocean:
color = "rgb(69, 91, 217)";
case Catan.T.Empty:
color = "rgb(255, 255, 255)";
break;
default:
throw "Can't find color for non-coast with this land type: '" + land + "'";
}
return color;
};
var getColorFromCoast = function (land) {
var color;
switch (land) {
case Catan.T.Hills:
color = "rgb(224, 129, 27)";
break;
case Catan.T.Pasture:
color = "rgb(43, 224, 27)";
break;
case Catan.T.Mountains:
color = "rgb(145, 145, 145)";
break;
case Catan.T.Fields:
color = "rgb(229, 255, 0)";
break;
case Catan.T.Forest:
color = "rgb(8, 150, 34)";
break;
case Catan.T.Empty:
color = "rgb(255, 255, 255)";
break;
default:
throw "Can't find color for coast with this land type: '" + land + "'";
}
return color;
};
@@ -72,7 +241,7 @@
cx = hexagon.position.column * (width + dist) - ((hexagon.position.line + 1) % 2) * (width + dist) / 2 + width/2 + size.canvasWidth/2 - mapWidth/2,
cy = hexagon.position.line * (3 / 4 * height + dist) + height/2 + size.canvasHeight/2 - mapHeight/2;

ctx.fillStyle = getColorFromTerrain(hexagon.terrain);
ctx.fillStyle = hexagon.isCoast() ? "rgb(69, 91, 217)" : getColorFromLand(hexagon.land);
ctx.beginPath();
ctx.moveTo(cx, cy - height / 2);
ctx.lineTo(cx + width / 2, cy - height / 4);
@@ -92,12 +261,12 @@
ctx.fill();
};

if (hexagon.terrain == Catan.T.Harbor) {
fillCircle(cx, cy, 11, getColorFromTerrain(hexagon.circle));
if (hexagon.isHarbor()) {
fillCircle(cx, cy, 11, getColorFromCoast(hexagon.land));
ctx.stroke();
}

if (Catan.debug) {
if (Catan.UI.debug) {
// draw coordinates
ctx.fillStyle = "rgb(0, 0, 0)";
ctx.font = "8pt Arial";
@@ -135,4 +304,5 @@
}
};

})(Catan);

})(Catan, PIXI);
256 changes: 228 additions & 28 deletions www/js/controllers.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,228 @@
angular.module('starter.controllers', [])

.controller('MapCtrl', function($scope, Settings) {
$scope.generate = function() {
Catan.generateMap(document.querySelector('.canvas'), Settings.getTileTrioScoreLimit());
};
// @todo: find another solution. This code wait for the interface to be loaded so that the "generate"
// button and bottom bar are loaded and so the canvas-container gets his final height
setTimeout(function(){
var canvas = document.querySelector('.canvas');
canvas.width = document.querySelector('.canvas-container').offsetWidth;
canvas.height = document.querySelector('.canvas-container').offsetHeight;

$scope.generate();
}, 200);
})

.controller('SettingsCtrl', function($scope, Settings) {
$scope.tileTrioScoreLimitElements = [
{value: 11, title: 'High (slower)'},
{value: 12, title: 'Normal'},
{value: 13, title: 'Low (faster)'}
];
$scope.selectedItem = Settings.setTileTrioScoreLimit() || $scope.tileTrioScoreLimitElements[1];
$scope.updateTileTrioScoreLimit = function() {
Settings.setTileTrioScoreLimit(this.selectedItem.value);
};
});
//noinspection JSHint
(function (angular, Catan) {
"use strict";

function MapData() {
this.map = null;
this.id = null;
this.thumbnailImageUri = null;
this.name = null;
this.catchPhrase = null;
}

angular.module('starter.controllers', [])

.controller('MapCtrl', ['$scope', '$ionicPlatform', '$timeout', 'Settings', 'Favorites', 'Image', 'Faker', 'Id', '$ionicAnalytics',
function ($scope, $ionicPlatform, $timeout, Settings, Favorites, Image, Faker, Id, $ionicAnalytics) {

$scope.generate = function () {
// generate map tiles
var mapData = new MapData();
mapData.map = Catan.Generator.Map.generate(Settings.getTileTrioScoreLimit(), Settings.getHarborGenerationStrategy());

// generate map id
mapData.id = Id.uuid();

// generate map name and catchphrase
mapData.name = Faker.getMapName();
mapData.catchPhrase = Faker.getMapCatchPhrase();

// store generation metadata
mapData.harborGenerationPhrase = {
'separate-tiles': 'Separate Tiles (18 tiles)',
'coast-bars': 'Enclosing edges bars (6 long pieces)'
}[Settings.getHarborGenerationStrategy()];
mapData.fairnessPhrase = {
11: 'Fair',
12: 'Normal',
13: 'Unfair'
}[Settings.getTileTrioScoreLimit()];

$scope.mapData = mapData;
$scope.starred = false;
};

$scope.starred = false;
$scope.starToggle = function () {
$timeout(function(){
$scope.starred = !$scope.starred;
if ($scope.starred) {
Favorites.save($scope.mapData);
$ionicAnalytics.track('star');
} else {
Favorites.remove($scope.mapData);
$ionicAnalytics.track('unstar');
}
});
};
}])

.controller('SettingsCtrl', ['$scope', 'Settings', '$ionicAnalytics', function ($scope, Settings, $ionicAnalytics) {
$scope.tileTrioScoreLimitOptions = [
{id: 11, label: 'High (slower)'},
{id: 12, label: 'Normal'},
{id: 13, label: 'Low (faster)'}
];
var selectedTileTrioScoreLimitValue = Settings.getTileTrioScoreLimit();
$scope.selectedTileTrioScoreLimit = null;
for (var i = 0; i < $scope.tileTrioScoreLimitOptions.length; i++) {
if ($scope.tileTrioScoreLimitOptions[i].id === selectedTileTrioScoreLimitValue) {
$scope.selectedTileTrioScoreLimit = $scope.tileTrioScoreLimitOptions[i];
}
}
$scope.updateTileTrioScoreLimit = function () {
var selectedId = this.selectedTileTrioScoreLimit.id;
Settings.setTileTrioScoreLimit(selectedId);
$ionicAnalytics.track('settings', {
type: 'tile-trio-limit',
value: $scope
.tileTrioScoreLimitOptions
.reduce(function(prev, curr){
return curr.id === selectedId ? curr : prev;
}, {})
.label
});
};


$scope.harborGenerationStrategyOptions = [
{id: 'separate-tiles', label: 'Separate Tiles (18 tiles)'},
{id: 'coast-bars', label: 'Enclosing edges bars (6 long pieces)'}
];
var selectedHarborGenerationStrategyValue = Settings.getHarborGenerationStrategy();
$scope.selectedHarborGenerationStrategy = null;
for (i = 0; i < $scope.harborGenerationStrategyOptions.length; i++) {
if ($scope.harborGenerationStrategyOptions[i].id === selectedHarborGenerationStrategyValue) {
$scope.selectedHarborGenerationStrategy = $scope.harborGenerationStrategyOptions[i];
}
}
$scope.updateHarborGenerationStrategy = function () {
var selectedId = this.selectedHarborGenerationStrategy.id;
Settings.setHarborGenerationStrategy(selectedId);

$ionicAnalytics.track('settings', {
type: 'harbor-generation-strategy',
value: $scope
.harborGenerationStrategyOptions
.reduce(function(prev, curr){
return curr.id === selectedId ? curr : prev;
}, {})
.label
});
};

$scope.uiDefinitionOptions = [
{id: 'low', label: 'Low Def. (homemade)'},
{id: 'high', label: 'High Def. (PIXI.js powered)'}
];
var selectedUiDefinitionValue = Settings.getUiDefinition();
$scope.selectedUiDefinition = null;
for (i = 0; i < $scope.uiDefinitionOptions.length; i++) {
if ($scope.uiDefinitionOptions[i].id === selectedUiDefinitionValue) {
$scope.selectedUiDefinition = $scope.uiDefinitionOptions[i];
}
}
$scope.updateUiDefinition = function () {
var selectedId = this.selectedUiDefinition.id;
Settings.setUiDefinition(selectedId);

$ionicAnalytics.track('settings', {
type: 'harbor-generation-strategy',
value: $scope
.uiDefinitionOptions
.reduce(function(prev, curr){
return curr.id === selectedId ? curr : prev;
}, {})
.label
});
};
}])

.controller('FavoritesCtrl', ['$scope', 'Favorites', '$ionicListDelegate', '$timeout',
function ($scope, Favorites, $ionicListDelegate, $timeout) {
$timeout(function () {
$scope.items = Favorites.fetchAll();
});

$scope.$on('$ionicView.enter', function (event, data) {
$timeout(function () {
$ionicListDelegate.showDelete(false);
$scope.items = Favorites.fetchAll();
});
});
$scope.$on('$ionicView.beforeLeave', function (event, data) {
$ionicListDelegate.showDelete(false);
});

$scope.toggleDeleteButtons = function () {
$ionicListDelegate.showDelete(!$ionicListDelegate.showDelete());
};

$scope.deleteItem = function (mapData) {
$timeout(function () {
Favorites.remove(mapData);
$scope.items = Favorites.fetchAll();
});
};
}])

.directive("map", ['Settings', 'Image', function (Settings, Image) {
return {
restrict: 'E',
scope: {
mapData: '=mapData',
generateThumbnail: '@generateThumbnail'
},
template: '<canvas></canvas>',
link: function (scope, element, attrs) {
var assetLoaded = false;

scope.canvasContainer = element[0];

var renderer = Catan.UI.HighDefinition.init(
scope.canvasContainer,
scope.canvasContainer.parentElement.offsetWidth,
scope.canvasContainer.parentElement.offsetHeight,
function (renderer) {
assetLoaded = true;
}
);

scope.$watch('mapData', function (mapData) {
if (!mapData) {
return;
}
var uiDefinition = Settings.getUiDefinition();
var canvas = scope.canvasContainer.childNodes[0];

if (uiDefinition === 'low') {
canvas.width = scope.canvasContainer.parentElement.offsetWidth;
canvas.height = scope.canvasContainer.parentElement.offsetHeight;
Catan.UI.LowDefinition.drawMap(mapData.map, canvas);
} else if (assetLoaded) {
Catan.UI.HighDefinition.draw(
renderer,
mapData.map,
scope.canvasContainer.parentElement.offsetWidth,
scope.canvasContainer.parentElement.offsetHeight
);
}

if (scope.generateThumbnail) {
Image.getCroppedAndResizedBase64Uri(canvas, function (thumbnailImageUri) {
scope.$apply(function () {
scope.mapData.thumbnailImageUri = thumbnailImageUri;
});
});
}
});
}
};
}])
.controller('FavoritesViewCtrl', ['$scope', 'mapData', function ($scope, mapData) {
$scope.mapData = mapData;
}])
;


})(angular, Catan);
234 changes: 223 additions & 11 deletions www/js/services.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,224 @@
angular.module('starter.services', ['LocalStorageModule'])

.factory('Settings', function (localStorageService) {
return {
getTileTrioScoreLimit: function () {
return localStorageService.get('tileTrioScoreLimit') || 12;
},
setTileTrioScoreLimit: function (tileTrioScoreLimit) {
localStorageService.set('tileTrioScoreLimit', tileTrioScoreLimit);
//noinspection JSHint
(function (angular, faker, Catan) {
"use strict";

angular.module('starter.services', ['LocalStorageModule'])

.factory('Settings', ['localStorageService', function (localStorageService) {
return {
getTileTrioScoreLimit: function () {
return localStorageService.get('tileTrioScoreLimit') || 13;
},
setTileTrioScoreLimit: function (tileTrioScoreLimit) {
localStorageService.set('tileTrioScoreLimit', tileTrioScoreLimit);
},

getHarborGenerationStrategy: function () {
return localStorageService.get('harborGenerationStrategy') || 'coast-bars';
},
setHarborGenerationStrategy: function (harborGenerationStrategy) {
localStorageService.set('harborGenerationStrategy', harborGenerationStrategy);
},

getUiDefinition: function () {
return localStorageService.get('uiDefinition') || 'high';
},
setUiDefinition: function (uiDefinition) {
localStorageService.set('uiDefinition', uiDefinition);
}
};
}])

.factory('Favorites', ['localStorageService', function (localStorageService) {
var saveAll = function (mapsData) {
var serializedMapsData = [];
for (var i = 0; i < mapsData.length; i++) {
mapsData[i].map = Catan.Map.serialize(mapsData[i].map);
serializedMapsData.push(mapsData[i]);
}
localStorageService.set('mapHistory', serializedMapsData);
};

var service = {
save: function (mapData) {
var mapsData = service.fetchAll();
mapsData.unshift(mapData);
saveAll(mapsData);
return mapData;
},
fetchAll: function () {
var mapsData = localStorageService.get('mapHistory') || [];
for (var i = 0; i < mapsData.length; i++) {
mapsData[i].map = Catan.Map.unserialize(mapsData[i].map);
}
return mapsData;
},
remove: function (mapToDelete) {
var maps = service.fetchAll();
var newMaps = [];
for (var i = 0; i < maps.length; i++) {
if (maps[i].id !== mapToDelete.id) {
newMaps.push(maps[i]);
}
}
saveAll(newMaps);
return newMaps;
},
fetchById: function (id) {
var maps = service.fetchAll();
for (var i = 0; i < maps.length; i++) {
if (maps[i].id === id) {
return maps[i];
}
}
return null;
}
};
return service;
}])

.factory('Image', function () {

function getNonWhiteCoordinates(canvas) {
// from http://stackoverflow.com/questions/12175991/crop-image-white-space-automatically-using-jquery
var context = canvas.getContext('2d');
var imgWidth = canvas.width, imgHeight = canvas.height,
imageData = context.getImageData(0, 0, imgWidth, imgHeight),
data = imageData.data,
getRBG = function (x, y) {
var offset = imgWidth * y + x;
return {
red: data[offset * 4],
green: data[offset * 4 + 1],
blue: data[offset * 4 + 2],
opacity: data[offset * 4 + 3]
};
},
isWhite = function (rgb) {
// many images contain noise, as the white is not a pure #fff white
return rgb.red > 200 && rgb.green > 200 && rgb.blue > 200;
},
scanY = function (fromTop) {
var offset = fromTop ? 1 : -1;

// loop through each row
for (var y = fromTop ? 0 : imgHeight - 1; fromTop ? (y < imgHeight) : (y > -1); y += offset) {

// loop through each column
for (var x = 0; x < imgWidth; x++) {
var rgb = getRBG(x, y);
if (!isWhite(rgb)) {
return y;
}
}
}
return null; // all image is white
},
scanX = function (fromLeft) {
var offset = fromLeft ? 1 : -1;

// loop through each column
for (var x = fromLeft ? 0 : imgWidth - 1; fromLeft ? (x < imgWidth) : (x > -1); x += offset) {

// loop through each row
for (var y = 0; y < imgHeight; y++) {
var rgb = getRBG(x, y);
if (!isWhite(rgb)) {
return x;
}
}
}
return null; // all image is white
};

var res = {
cropTop: scanY(true),
cropBottom: scanY(false),
cropLeft: scanX(true),
cropRight: scanX(false)
};
res.cropWidth = res.cropRight - res.cropLeft;
res.cropHeight = res.cropBottom - res.cropTop;

return res;
}
};
});

var Image = {
getThumbnailWidth: function () {
return 150;
},
getThumbnailHeight: function () {
return 150;
},
getCroppedAndResizedBase64Uri: function (canvasToCropAndResize, callback, wantedWidth, wantedHeight) {
wantedWidth = wantedWidth || Image.getThumbnailWidth();
wantedHeight = wantedHeight || Image.getThumbnailHeight();

var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
var imageObj = document.createElement('img');

var cropCoordinates = getNonWhiteCoordinates(canvasToCropAndResize);

imageObj.onload = function () {

// draw cropped image based on http://www.html5canvastutorials.com/tutorials/html5-canvas-image-crop/
var sourceX = cropCoordinates.cropLeft;
var sourceY = cropCoordinates.cropTop;
var sourceWidth = cropCoordinates.cropWidth;
var sourceHeight = cropCoordinates.cropHeight;
var destWidth = Image.getThumbnailWidth();
var destHeight = Image.getThumbnailHeight();
var destX = 0;
var destY = 0;

canvas.width = destWidth;
canvas.height = destHeight;
context.drawImage(imageObj, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight);

callback(canvas.toDataURL());
};

imageObj.src = canvasToCropAndResize.toDataURL();
}
};

return Image;
})

.factory('Faker', function () {
return {
getMapName: function () {
return faker.address.city() + ' ' + faker.address.streetSuffix();
},
getMapCatchPhrase: function () {
return faker.company.catchPhrase();
}
};
})

.factory('Id', ['localStorageService', function (localStorageService) {
var Id = {
next: function () {
var next = Id.current() + 1;
localStorageService.set('uniqid', next);
return next;
},
current: function () {
return localStorageService.get('uniqid') || 1;
},
uuid: function () {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
}
};
return Id;
}])
;

})(angular, faker, Catan);
19 changes: 0 additions & 19 deletions www/lib/angular-animate/.bower.json

This file was deleted.

77 changes: 0 additions & 77 deletions www/lib/angular-animate/README.md

This file was deleted.

2,137 changes: 0 additions & 2,137 deletions www/lib/angular-animate/angular-animate.js

This file was deleted.

33 changes: 0 additions & 33 deletions www/lib/angular-animate/angular-animate.min.js

This file was deleted.

8 changes: 0 additions & 8 deletions www/lib/angular-animate/angular-animate.min.js.map

This file was deleted.

9 changes: 0 additions & 9 deletions www/lib/angular-animate/bower.json

This file was deleted.

26 changes: 0 additions & 26 deletions www/lib/angular-animate/package.json

This file was deleted.

41 changes: 0 additions & 41 deletions www/lib/angular-local-storage/.bower.json

This file was deleted.

3 changes: 0 additions & 3 deletions www/lib/angular-local-storage/.bowerrc

This file was deleted.

1 change: 0 additions & 1 deletion www/lib/angular-local-storage/.gitattributes

This file was deleted.

8 changes: 0 additions & 8 deletions www/lib/angular-local-storage/.gitignore

This file was deleted.

9 changes: 0 additions & 9 deletions www/lib/angular-local-storage/.travis.yml

This file was deleted.

8 changes: 0 additions & 8 deletions www/lib/angular-local-storage/CHANGELOG.md

This file was deleted.

8 changes: 0 additions & 8 deletions www/lib/angular-local-storage/LICENSE

This file was deleted.

Loading