From 71dde45ce8a917220a448ea71fd682d5d3eb3146 Mon Sep 17 00:00:00 2001 From: llaske Date: Wed, 24 Apr 2013 08:22:25 +0000 Subject: Second version. Fix issue on play sound. Network version. --- diff --git a/README.md b/README.md index 571c16b..aa188d2 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,16 @@ # What is Abecedarium ? -Abecedarium activity for Sugar. - +Abecedarium is an abecedary activity to learn its alphabet using images, sounds and words. + +Abecedarium has two parts: +* Learn: To explore the words by letters or by theme (Nature, Body parts, Things, Concepts), +* Play: Six little games to match pictures/sounds/words with possibility to filter by letter or by theme, +* Build: It will allow to build little stories combining images and sounds from the database. + +All words could be seen in upper case, lower case or script. +Abecedarium could be use both in English (about 500 words in the database) and in French (about 1000 words in the database). +All contents come from the Art4apps library. See Credits page for more. + # How it works ? @@ -26,6 +35,11 @@ All the HTML5/JavaScript is in this directory. * styles.css contains all CSS class used * package.js list all javascript files to load * app.js is the main screen +* learngame.js is the first game +* playgame.js is the second game +* buildgame.js is the third game +* credits.js is the credit screen +* all other .js files are component used by the games ## /html/enyo and /html/lib diff --git a/activity.py b/activity.py index c0ca284..c12ee94 100644 --- a/activity.py +++ b/activity.py @@ -163,6 +163,7 @@ class AbecedariumActivity(activity.Activity): file = open(self.file_path, 'w') try: file.write(context['context']+'\n') + file.write(context['database']+'\n') finally: file.close() @@ -173,6 +174,7 @@ class AbecedariumActivity(activity.Activity): self.context = {} try: self.context['context'] = file.readline().strip('\n') + self.context['database'] = file.readline().strip('\n') finally: file.close() diff --git a/activity/activity.info b/activity/activity.info index d280e83..8e647e6 100644 --- a/activity/activity.info +++ b/activity/activity.info @@ -1,6 +1,6 @@ [Activity] name = Abecedarium -activity_version = 1 +activity_version = 2 bundle_id = org.olpcfrance.Abecedarium exec = sugar-activity activity.AbecedariumActivity icon = activity-abecedarium diff --git a/html/app.js b/html/app.js index 3579d8a..45b2b9b 100644 --- a/html/app.js +++ b/html/app.js @@ -19,9 +19,11 @@ enyo.kind({ {name: "credit", kind: "Image", src: "images/credit.png", classes: "creditButton", ontap: "displayCredits"}, {name: "learn", kind: "Image", src: "images/learn.png", classes: "learnButton", ontap: "learnGame"}, {name: "play", kind: "Image", src: "images/play.png", classes: "playButton", ontap: "playGame"}, - {name: "build", kind: "Image", src: "images/build.png", classes: "buildButton", ontap: "buildGame"} + {name: "build", kind: "Image", src: "images/build.png", classes: "buildButton", ontap: "buildGame"}, + {name: "networkCheck", kind: "Abcd.NetworkCheck", ontap: "networkSettings"} ]}, {name: "creditsPopup", kind: "Abcd.CreditsPopup"}, + {name: "networkPopup", kind: "Abcd.NetworkPopup", onNetworkChanged: "networkChanged"}, {kind: "Signals", onEndOfSound: "endOfSound", onSoundTimeupdate: "soundTimeupdate"} ], @@ -43,6 +45,7 @@ enyo.kind({ } this.playTheme(); Abcd.context.object = null; + this.$.networkCheck.check(); }, // Play theme @@ -55,7 +58,6 @@ enyo.kind({ // Launch activities learnGame: function(e, s) { Abcd.sound.pause(); - Abcd.context.object = new Abcd.Learn().renderInto(document.getElementById("body")); }, @@ -69,6 +71,15 @@ enyo.kind({ this.$.creditsPopup.show(); }, + // Handle: display network settings popup and handle change + networkSettings: function(e, s) { + this.$.networkPopup.display(); + }, + + networkChanged: function() { + this.$.networkCheck.check(); + }, + // Sound ended, play next instrument endOfSound: function(e, s) { if (s == soundThemes[this.soundindex]) diff --git a/html/buttons.js b/html/buttons.js index e53af37..1a95385 100644 --- a/html/buttons.js +++ b/html/buttons.js @@ -94,7 +94,7 @@ enyo.kind({ }); -// Collection component +// Play type button enyo.kind({ name: "Abcd.PlayTypeButton", published: { from: "", to: "", theme: null }, @@ -139,4 +139,4 @@ enyo.kind({ var src = "images/"+this.to+".png"; this.$.imageTo.setAttribute("src", src); } -}); \ No newline at end of file +}); diff --git a/html/collection.js b/html/collection.js index 4c9c2b5..d6ddd38 100644 --- a/html/collection.js +++ b/html/collection.js @@ -7,7 +7,7 @@ enyo.kind({ components: [ { name: "spinner", kind: "Image", src: "images/spinner-light.gif", classes: "spinner-small"}, { name: "contentBox", showing: false, components: [ - { name: "itemImage", classes: "collectionImage", kind: "Image", onload: "imageLoaded" }, + { name: "itemImage", classes: "collectionImage", kind: "Image", onload: "imageLoaded", onerror: "imageError" }, { name: "itemText", classes: "collectionText" } ]} ], @@ -25,6 +25,11 @@ enyo.kind({ this.$.contentBox.show(); } }, + + // Error loading image, probably lost connection to database + imageError: function() { + Abcd.goHome(); + }, // Localization changed, update text setLocale: function() { @@ -36,13 +41,13 @@ enyo.kind({ indexChanged: function() { var collection = Abcd.collections[this.index]; var entry = Abcd.entries[collection.img]; - var image = "images/database/"+entry.code+".png"; + var image = Abcd.context.database+"images/database/"+entry.code+".png"; var text = __$FC(collection.text); if (Abcd.context.casevalue == 1) text = text.toUpperCase(); this.$.itemImage.setAttribute("src", image); this.$.itemText.removeClass("collectionText0"); - this.$.itemText.removeClass("collectionText1"); + this.$.itemText.removeClass("colle0ctionText1"); this.$.itemText.removeClass("collectionText2"); this.$.itemText.addClass("collectionText"+Abcd.context.casevalue); this.$.itemText.setContent(text); diff --git a/html/config.js b/html/config.js new file mode 100644 index 0000000..e7650b4 --- /dev/null +++ b/html/config.js @@ -0,0 +1,10 @@ + +// Database localisation: +// - set to empty string "" for local database +// - set url prefix for distant hosting + +// Local database +Abcd.context.database = ""; + +// Internet database +//Abcd.context.database = "http://laske.fr/abecedarium/"; diff --git a/html/credits.js b/html/credits.js index bc0761d..707f704 100644 --- a/html/credits.js +++ b/html/credits.js @@ -22,7 +22,9 @@ enyo.kind({ { content: "jon trillana from The Noun Project (Lego icon)", classes: "credit-name" }, { content: "Patrick N. from The Noun Project (funnel icon)", classes: "credit-name" }, { content: "John Caserta from The Noun Project (trash can icon)", classes: "credit-name" }, + { content: "Robert Leonardo from The Noun Project (warning icon)", classes: "credit-name" }, { content: "The Noun Project (picture icon)", classes: "credit-name" }, + { content: "Sugar (network 100% icon)", classes: "credit-name" }, { content: "music:", classes: "credit-title" }, { content: "Alphabet song French traditional song play by Finale NotePad", classes: "credit-name" }, { content: "sounds effects:", classes: "credit-title" }, diff --git a/html/depends.js b/html/depends.js index 6c689b1..6ca0253 100644 --- a/html/depends.js +++ b/html/depends.js @@ -2,6 +2,8 @@ "sugar.js", "util.js", "database.js", + "config.js", + "network.js", "l10n.js", "audio.js", "item.js", diff --git a/html/entry.js b/html/entry.js index 5107cd8..ea25a5f 100644 --- a/html/entry.js +++ b/html/entry.js @@ -7,7 +7,7 @@ enyo.kind({ components: [ { name: "spinner", kind: "Image", src: "images/spinner-light.gif", classes: "spinner"}, { name: "contentBox", showing: false, components: [ - { name: "itemImage", classes: "entryImage", kind: "Image", onload: "imageLoaded" }, + { name: "itemImage", classes: "entryImage", kind: "Image", onload: "imageLoaded", onerror: "imageError" }, { name: "soundIcon", kind: "Image", classes: "entrySoundIcon" }, { name: "itemText", classes: "entryText" } ]}, @@ -34,6 +34,11 @@ enyo.kind({ this.$.contentBox.show(); } }, + + // Error loading image, probably lost connection to database + imageError: function() { + Abcd.goHome(); + }, // Unique visibility options imageonlyChanged: function() { @@ -61,7 +66,7 @@ enyo.kind({ indexChanged: function() { // Get content var entry = Abcd.entries[this.index]; - var image = "images/database/"+entry.code+".png"; + var image = Abcd.context.database+"images/database/"+entry.code+".png"; var text = __$FC(entry.text); if (Abcd.context.casevalue == 1) text = text.toUpperCase(); @@ -69,7 +74,7 @@ enyo.kind({ // Get sound if (this.soundonly) this.$.soundIcon.addClass("entrySoundIconOnly"); if (entry[Abcd.context.lang]) { - this.sound = "audio/"+Abcd.context.lang+"/database/"+entry.code; + this.sound = Abcd.context.database+"audio/"+Abcd.context.lang+"/database/"+entry.code; this.$.soundIcon.setSrc("images/sound_off"+(this.soundonly?1:0)+".png"); } else { this.sound = null; diff --git a/html/images/checkw.png b/html/images/checkw.png new file mode 100644 index 0000000..d18d85e --- /dev/null +++ b/html/images/checkw.png Binary files differ diff --git a/html/images/network-black.png b/html/images/network-black.png new file mode 100644 index 0000000..24d2f35 --- /dev/null +++ b/html/images/network-black.png Binary files differ diff --git a/html/images/network-ko.png b/html/images/network-ko.png new file mode 100644 index 0000000..cfcc3f5 --- /dev/null +++ b/html/images/network-ko.png Binary files differ diff --git a/html/images/network-ok.png b/html/images/network-ok.png new file mode 100644 index 0000000..74d3ff1 --- /dev/null +++ b/html/images/network-ok.png Binary files differ diff --git a/html/learn.js b/html/learn.js index cd54042..bff86bb 100644 --- a/html/learn.js +++ b/html/learn.js @@ -219,10 +219,11 @@ enyo.kind({ this.displayEntriesFrom(Math.max(0,this.entry-entriesByScreen-this.entry%entriesByScreen)); }, - backTaped: function() { + backTaped: function() { var current = this.$.box.getControls()[0]; this.entry = -1; if (current.kind == "Abcd.Entry" && this.theme != 4) { + this.collection = -1; this.displayCollections({index: this.theme}); this.$.box.removeClass("box-4-entry"); return; diff --git a/html/letter.js b/html/letter.js index f6a8ab7..97982e5 100644 --- a/html/letter.js +++ b/html/letter.js @@ -36,6 +36,6 @@ enyo.kind({ // Play sound for this letter play: function(media) { - media.play("audio/"+Abcd.context.lang+"/database/upper_"+this.letter.toUpperCase()); + media.play(Abcd.context.database+"audio/"+Abcd.context.lang+"/database/upper_"+this.letter.toUpperCase()); } }); \ No newline at end of file diff --git a/html/network.js b/html/network.js new file mode 100644 index 0000000..b8a735e --- /dev/null +++ b/html/network.js @@ -0,0 +1,98 @@ + + +// Network check component +enyo.kind({ + name: "Abcd.NetworkCheck", + kind: enyo.Control, + classes: "networkCheck", + components: [ + {name: "box", components: []}, + {name: "networkChecking", kind: "Image", src: "images/spinner-light.gif", showing: false, classes: "networkIcon"}, + {name: "networkOK", kind: "Image", src: "images/network-ok.png", showing: false, classes: "networkIcon"}, + {name: "networkKO", kind: "Image", src: "images/network-ko.png", showing: false, classes: "networkIcon"} + ], + + // Constructor + rendered: function() { + this.inherited(arguments); + }, + + // Check the connection + check: function() { + // Not needed when local database used + if (Abcd.context.database == "") { + Abcd.changeVisibility(this, {networkChecking: false, networkOK: false, networkKO: false}); + return; + } + Abcd.changeVisibility(this, {networkChecking: true, networkOK: false, networkKO: false}); + + // Remove previous attempt + var items = []; + enyo.forEach(this.$.box.getControls(), function(item) { + items.push(item); + }); + for (var i = 0 ; i < items.length ; i++) { + items[i].destroy(); + } + + // Ping network + this.$.networkChecking.show(); + this.$.box.createComponent( + {kind: "Image", showing: false, src: Abcd.context.database+"images/database/_ping.png?"+(new Date()).getTime(), onload: "networkOK", onerror: "networkKO"}, + {owner: this} + ).render(); + }, + + // Update icons depending of network response + networkOK: function() { + Abcd.changeVisibility(this, {networkChecking: false, networkOK: true, networkKO: false}); + }, + + networkKO: function() { + Abcd.changeVisibility(this, {networkChecking: false, networkOK: false, networkKO: true}); + } +}); + + +// Network setting popup +enyo.kind({ + name: "Abcd.NetworkPopup", + kind: "onyx.Popup", + classes: "network-popup", + centered: true, + modal: true, + floating: true, + events: { + onNetworkChanged: "" + }, + components: [ + {kind: "Image", src: "images/network-black.png", classes: "networkbImage"}, + {name: "settings", kind: "enyo.Input", classes: "networkValue"}, + {kind: "Image", src: "images/checkw.png", classes: "checkwButton", ontap: "checkTaped"} + ], + + // Constructor + create: function() { + this.inherited(arguments); + }, + + rendered: function() { + this.inherited(arguments); + }, + + // Display popup with current database value + display: function() { + this.$.settings.setValue(Abcd.context.database); + this.show(); + this.$.settings.hasNode().focus(); + }, + + // Check taped, set the new value, recheck + checkTaped: function() { + var newvalue = this.$.settings.getValue(); + if (newvalue != "") + Abcd.context.database = this.$.settings.getValue(); + this.hide(); + this.doNetworkChanged(); + } +}); \ No newline at end of file diff --git a/html/play.js b/html/play.js index 42ed6e8..18a7be9 100644 --- a/html/play.js +++ b/html/play.js @@ -287,6 +287,7 @@ enyo.kind({ this.$.colorBar.removeClass("themeColor"+this.theme); this.theme = -1; this.gamecount = 0; + this.selected = null; this.displayButtons(); }, @@ -300,7 +301,6 @@ enyo.kind({ this.selected = this.from; this.selected.addClass("entryPlayWrong"); } else if (this.selected.index == this.from.index) { - this.check4end = true; Abcd.sound.play("audio/applause"); this.selected.removeClass("entryPlaySelected"); this.selected.addClass("entryPlayRight"); @@ -313,6 +313,10 @@ enyo.kind({ // End sound endSound: function(e, s) { + // Prematured end + if (this.selected == null) + return; + // Bad check, retry if (s == "audio/disappointed") { this.selected.removeClass("entryPlaySelected"); diff --git a/html/styles.css b/html/styles.css index 258e7a6..4b33534 100644 --- a/html/styles.css +++ b/html/styles.css @@ -465,7 +465,7 @@ .credits-popup { width: 880px; - height: 550px; + height: 600px; color: black; } @@ -488,4 +488,36 @@ font-size: 16px; margin-left: 300px; color: white; -} \ No newline at end of file +} + +.networkIcon { + position: absolute; + top: 530px; + right: 50px; +} + +.network-popup { + width: 880px; + height: 200px; + color: black; +} + +.networkbImage { + position: absolute; + top: 40px; + left: 10px; +} + +.networkValue { + position: absolute; + left: 100px; + margin-top: 35px; + font-size: 38px; + width: 760px; +} + +.checkwButton { + position: absolute; + bottom: 10px; + right: 30px; +} diff --git a/html/theme.js b/html/theme.js index cad51e3..e06eaa8 100644 --- a/html/theme.js +++ b/html/theme.js @@ -7,7 +7,7 @@ enyo.kind({ components: [ { name: "spinner", kind: "Image", src: "images/spinner-light.gif", classes: "spinner"}, { name: "contentBox", showing: false, components: [ - { name: "itemImage", classes: "themeImage", kind: "Image", onload: "imageLoaded" }, + { name: "itemImage", classes: "themeImage", kind: "Image", onload: "imageLoaded", onerror: "imageError" }, { name: "itemText", classes: "themeText" } ]} ], @@ -25,6 +25,11 @@ enyo.kind({ this.$.contentBox.show(); } }, + + // Error loading image, probably lost connection to database + imageError: function() { + Abcd.goHome(); + }, // Localization changed, update text setLocale: function() { @@ -36,7 +41,7 @@ enyo.kind({ indexChanged: function() { var theme = Abcd.themes[this.index]; var entry = Abcd.entries[theme.img]; - var image = "images/database/"+entry.code+".png"; + var image = Abcd.context.database+"images/database/"+entry.code+".png"; var text = __$FC(theme.text); if (Abcd.context.casevalue == 1) text = text.toUpperCase(); diff --git a/html/util.js b/html/util.js index f4efec1..dce26ca 100644 --- a/html/util.js +++ b/html/util.js @@ -7,6 +7,7 @@ Abcd = {}; // Game context handling Abcd.context = { + database: "", home: null, object: null, screen: "", @@ -20,7 +21,7 @@ Abcd.saveContext = function() { values.push(Abcd.context.lang); values.push(Abcd.context.casevalue); values.push(Abcd.context.object!=null?Abcd.context.object.saveContext():""); - Abcd.sugar.sendMessage("save-context", {context:values.join("#")}); + Abcd.sugar.sendMessage("save-context", {context:values.join("#"), database:Abcd.context.database}); }; Abcd.loadContext = function(context) { if (context == null || context == "" || !context.context) @@ -31,6 +32,9 @@ Abcd.loadContext = function(context) { Abcd.context.casevalue = values[2]; Abcd.context.screenContext = values[3]; Abcd.setLocale(Abcd.context.lang); + if (context.database) { + Abcd.context.database = context.database; + } }; @@ -62,6 +66,8 @@ Abcd.log = function(msg) { // Home handling Abcd.goHome = function() { if (Abcd.context.home != null) { + if (Abcd.context.object == null) + return; Abcd.context.screen = ""; Abcd.context.home.renderInto(document.getElementById("body")); Abcd.context.home.playTheme(); -- cgit v0.9.1