Merge lp:~ken-vandine/dropping-letters/packaging into lp:dropping-letters

Proposed by Ken VanDine
Status: Merged
Approved by: Stuart Langridge
Approved revision: 27
Merged at revision: 23
Proposed branch: lp:~ken-vandine/dropping-letters/packaging
Merge into: lp:dropping-letters
Diff against target: 2897 lines (+457/-1148)
11 files modified
debian/changelog (+5/-0)
debian/compat (+1/-0)
debian/control (+16/-0)
debian/copyright (+368/-0)
debian/install (+17/-0)
debian/rules (+7/-0)
debian/source/format (+1/-0)
dropping-letters-ubuntu.qml (+0/-602)
dropping-letters.desktop (+11/-0)
dropping-letters.qml (+0/-546)
dropping-letters.qmlproject (+31/-0)
To merge this branch: bzr merge lp:~ken-vandine/dropping-letters/packaging
Reviewer Review Type Date Requested Status
Stuart Langridge Approve
Review via email: mp+161774@code.launchpad.net

Description of the change

Added packaging and minor cleanup

To post a comment you must log in.
26. By Ken VanDine

fixed icon path

27. By Ken VanDine

Use a MainView and set applicationName

Revision history for this message
Stuart Langridge (sil) wrote :

rubberstamp, cos: ken.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== renamed file 'Easy Lemon 60 second.ogg' => 'Easy_Lemon_60_second.ogg'
2=== added directory 'debian'
3=== added file 'debian/changelog'
4--- debian/changelog 1970-01-01 00:00:00 +0000
5+++ debian/changelog 2013-05-01 06:18:24 +0000
6@@ -0,0 +1,5 @@
7+dropping-letters (0.1) UNRELEASED; urgency=low
8+
9+ * Initial Release.
10+
11+ -- Ken VanDine <ken.vandine@canonical.com> Tue, 30 Apr 2013 21:41:31 -0700
12
13=== added file 'debian/compat'
14--- debian/compat 1970-01-01 00:00:00 +0000
15+++ debian/compat 2013-05-01 06:18:24 +0000
16@@ -0,0 +1,1 @@
17+9
18
19=== added file 'debian/control'
20--- debian/control 1970-01-01 00:00:00 +0000
21+++ debian/control 2013-05-01 06:18:24 +0000
22@@ -0,0 +1,16 @@
23+Source: dropping-letters
24+Section: games
25+Priority: extra
26+Maintainer: Alan Pope <popey@ubuntu.com>
27+Build-Depends: debhelper (>= 9.0.0)
28+Standards-Version: 3.9.4
29+Homepage: http://launchpad.net/dropping-letters
30+Vcs-Bzr: https://code.launchpad.net/~sil/dropping-letters
31+
32+Package: dropping-letters
33+Architecture: all
34+Depends: ${misc:Depends},qtdeclarative5-localstorage-plugin,qtdeclarative5-particles-plugin,qtdeclarative5-qtmultimedia-plugin,qtdeclarative5-qtquick2-plugin,qtdeclarative5-ubuntu-ui-toolkit-plugin|qt-components-ubuntu,qtdeclarative5-window-plugin,qtdeclarative5-xmllistmodel-plugin,qmlscene
35+Description: Dropping Letters game
36+ Build up words from falling letters to score
37+ points. Don't let the letters build up to the
38+ top of the screen.
39
40=== added file 'debian/copyright'
41--- debian/copyright 1970-01-01 00:00:00 +0000
42+++ debian/copyright 2013-05-01 06:18:24 +0000
43@@ -0,0 +1,368 @@
44+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
45+Upstream-Name: dropping-letters
46+Source: https://launchpad.net/dropping-letters
47+
48+Files: *
49+Copyright: 2013 Stuart Langridge <stuart.langridge@canonical.com>
50+License: GPL-3.0+
51+
52+Files: *.ogg
53+Copyright: 2013 Kevin MacLeod <kevin@incompetech.com>
54+Source: http://incompetech.com/music/royalty-free/index.html?isrc=USUAN1200077
55+License: CC-BY-3.0
56+
57+Files: debian/*
58+Copyright: 2013 Alan Pope <popey@ubuntu.com>
59+License: GPL-3.0+
60+
61+License: GPL-3.0+
62+ This program is free software: you can redistribute it and/or modify
63+ it under the terms of the GNU General Public License as published by
64+ the Free Software Foundation, either version 3 of the License, or
65+ (at your option) any later version.
66+ .
67+ This package is distributed in the hope that it will be useful,
68+ but WITHOUT ANY WARRANTY; without even the implied warranty of
69+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
70+ GNU General Public License for more details.
71+ .
72+ You should have received a copy of the GNU General Public License
73+ along with this program. If not, see <http://www.gnu.org/licenses/>.
74+ .
75+ On Debian systems, the complete text of the GNU General
76+ Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
77+
78+License: CC-BY-3.0
79+ Creative Commons Attribution 3.0 Unported
80+ .
81+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
82+ LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN
83+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION
84+ ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE
85+ INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
86+ ITS USE.
87+ .
88+ License
89+ .
90+ THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE
91+ COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY
92+ COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS
93+ AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
94+ .
95+ BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE
96+ TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY
97+ BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS
98+ CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND
99+ CONDITIONS.
100+ .
101+ 1. Definitions
102+ .
103+ a. "Adaptation" means a work based upon the Work, or upon the Work and
104+ other pre-existing works, such as a translation, adaptation, derivative
105+ work, arrangement of music or other alterations of a literary or
106+ artistic work, or phonogram or performance and includes cinematographic
107+ adaptations or any other form in which the Work may be recast,
108+ transformed, or adapted including in any form recognizably derived from
109+ the original, except that a work that constitutes a Collection will not
110+ be considered an Adaptation for the purpose of this License. For the
111+ avoidance of doubt, where the Work is a musical work, performance or
112+ phonogram, the synchronization of the Work in timed-relation with a
113+ moving image ("synching") will be considered an Adaptation for the
114+ purpose of this License.
115+ .
116+ b. "Collection" means a collection of literary or artistic works, such
117+ as encyclopedias and anthologies, or performances, phonograms or
118+ broadcasts, or other works or subject matter other than works listed in
119+ Section 1(f) below, which, by reason of the selection and arrangement of
120+ their contents, constitute intellectual creations, in which the Work is
121+ included in its entirety in unmodified form along with one or more other
122+ contributions, each constituting separate and independent works in
123+ themselves, which together are assembled into a collective whole. A work
124+ that constitutes a Collection will not be considered an Adaptation (as
125+ defined above) for the purposes of this License.
126+ .
127+ c. "Distribute" means to make available to the public the original and
128+ copies of the Work or Adaptation, as appropriate, through sale or other
129+ transfer of ownership.
130+ .
131+ d. "Licensor" means the individual, individuals, entity or entities that
132+ offer(s) the Work under the terms of this License.
133+ .
134+ e. "Original Author" means, in the case of a literary or artistic work,
135+ the individual, individuals, entity or entities who created the Work or
136+ if no individual or entity can be identified, the publisher; and in
137+ addition (i) in the case of a performance the actors, singers,
138+ musicians, dancers, and other persons who act, sing, deliver, declaim,
139+ play in, interpret or otherwise perform literary or artistic works or
140+ expressions of folklore; (ii) in the case of a phonogram the producer
141+ being the person or legal entity who first fixes the sounds of a
142+ performance or other sounds; and, (iii) in the case of broadcasts, the
143+ organization that transmits the broadcast.
144+ .
145+ f. "Work" means the literary and/or artistic work offered under the
146+ terms of this License including without limitation any production in the
147+ literary, scientific and artistic domain, whatever may be the mode or
148+ form of its expression including digital form, such as a book, pamphlet
149+ and other writing; a lecture, address, sermon or other work of the same
150+ nature; a dramatic or dramatico-musical work; a choreographic work or
151+ entertainment in dumb show; a musical composition with or without words;
152+ a cinematographic work to which are assimilated works expressed by a
153+ process analogous to cinematography; a work of drawing, painting,
154+ architecture, sculpture, engraving or lithography; a photographic work
155+ to which are assimilated works expressed by a process analogous to
156+ photography; a work of applied art; an illustration, map, plan, sketch
157+ or three-dimensional work relative to geography, topography,
158+ architecture or science; a performance; a broadcast; a phonogram; a
159+ compilation of data to the extent it is protected as a copyrightable
160+ work; or a work performed by a variety or circus performer to the extent
161+ it is not otherwise considered a literary or artistic work.
162+ .
163+ g. "You" means an individual or entity exercising rights under this
164+ License who has not previously violated the terms of this License with
165+ respect to the Work, or who has received express permission from the
166+ Licensor to exercise rights under this License despite a previous
167+ violation.
168+ .
169+ h. "Publicly Perform" means to perform public recitations of the Work
170+ and to communicate to the public those public recitations, by any means
171+ or process, including by wire or wireless means or public digital
172+ performances; to make available to the public Works in such a way that
173+ members of the public may access these Works from a place and at a place
174+ individually chosen by them; to perform the Work to the public by any
175+ means or process and the communication to the public of the performances
176+ of the Work, including by public digital performance; to broadcast and
177+ rebroadcast the Work by any means including signs, sounds or images.
178+ .
179+ i. "Reproduce" means to make copies of the Work by any means including
180+ without limitation by sound or visual recordings and the right of
181+ fixation and reproducing fixations of the Work, including storage of a
182+ protected performance or phonogram in digital form or other electronic
183+ medium.
184+ .
185+ 2. Fair Dealing Rights. Nothing in this License is intended to reduce,
186+ limit, or restrict any uses free from copyright or rights arising from
187+ limitations or exceptions that are provided for in connection with the
188+ copyright protection under copyright law or other applicable laws.
189+ .
190+ 3. License Grant. Subject to the terms and conditions of this License,
191+ Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
192+ perpetual (for the duration of the applicable copyright) license to
193+ exercise the rights in the Work as stated below:
194+ .
195+ a. to Reproduce the Work, to incorporate the Work into one or more
196+ Collections, and to Reproduce the Work as incorporated in the
197+ Collections;
198+ .
199+ b. to create and Reproduce Adaptations provided that any such
200+ Adaptation, including any translation in any medium, takes reasonable
201+ steps to clearly label, demarcate or otherwise identify that changes
202+ were made to the original Work. For example, a translation could be
203+ marked "The original work was translated from English to Spanish," or a
204+ modification could indicate "The original work has been modified.";
205+ .
206+ c. to Distribute and Publicly Perform the Work including as incorporated
207+ in Collections; and,
208+ .
209+ d. to Distribute and Publicly Perform Adaptations.
210+ .
211+ e. For the avoidance of doubt:
212+ .
213+ i. Non-waivable Compulsory License Schemes. In those jurisdictions in
214+ which the right to collect royalties through any statutory or compulsory
215+ licensing scheme cannot be waived, the Licensor reserves the exclusive
216+ right to collect such royalties for any exercise by You of the rights
217+ granted under this License;
218+ .
219+ ii. Waivable Compulsory License Schemes. In those jurisdictions in which
220+ the right to collect royalties through any statutory or compulsory
221+ licensing scheme can be waived, the Licensor waives the exclusive right
222+ to collect such royalties for any exercise by You of the rights granted
223+ under this License; and,
224+ .
225+ iii. Voluntary License Schemes. The Licensor waives the right to collect
226+ royalties, whether individually or, in the event that the Licensor is a
227+ member of a collecting society that administers voluntary licensing
228+ schemes, via that society, from any exercise by You of the rights
229+ granted under this License.
230+ .
231+ The above rights may be exercised in all media and formats whether now
232+ known or hereafter devised. The above rights include the right to make
233+ such modifications as are technically necessary to exercise the rights
234+ in other media and formats. Subject to Section 8(f), all rights not
235+ expressly granted by Licensor are hereby reserved.
236+ .
237+ 4. Restrictions. The license granted in Section 3 above is expressly
238+ made subject to and limited by the following restrictions:
239+ .
240+ a. You may Distribute or Publicly Perform the Work only under the terms
241+ of this License. You must include a copy of, or the Uniform Resource
242+ Identifier (URI) for, this License with every copy of the Work You
243+ Distribute or Publicly Perform. You may not offer or impose any terms on
244+ the Work that restrict the terms of this License or the ability of the
245+ recipient of the Work to exercise the rights granted to that recipient
246+ under the terms of the License. You may not sublicense the Work. You
247+ must keep intact all notices that refer to this License and to the
248+ disclaimer of warranties with every copy of the Work You Distribute or
249+ Publicly Perform. When You Distribute or Publicly Perform the Work, You
250+ may not impose any effective technological measures on the Work that
251+ restrict the ability of a recipient of the Work from You to exercise the
252+ rights granted to that recipient under the terms of the License. This
253+ Section 4(a) applies to the Work as incorporated in a Collection, but
254+ this does not require the Collection apart from the Work itself to be
255+ made subject to the terms of this License. If You create a Collection,
256+ upon notice from any Licensor You must, to the extent practicable,
257+ remove from the Collection any credit as required by Section 4(b), as
258+ requested. If You create an Adaptation, upon notice from any Licensor
259+ You must, to the extent practicable, remove from the Adaptation any
260+ credit as required by Section 4(b), as requested.
261+ .
262+ b. If You Distribute, or Publicly Perform the Work or any Adaptations or
263+ Collections, You must, unless a request has been made pursuant to
264+ Section 4(a), keep intact all copyright notices for the Work and
265+ provide, reasonable to the medium or means You are utilizing: (i) the
266+ name of the Original Author (or pseudonym, if applicable) if supplied,
267+ and/or if the Original Author and/or Licensor designate another party or
268+ parties (e.g., a sponsor institute, publishing entity, journal) for
269+ attribution ("Attribution Parties") in Licensor's copyright notice,
270+ terms of service or by other reasonable means, the name of such party or
271+ parties; (ii) the title of the Work if supplied; (iii) to the extent
272+ reasonably practicable, the URI, if any, that Licensor specifies to be
273+ associated with the Work, unless such URI does not refer to the
274+ copyright notice or licensing information for the Work; and (iv) ,
275+ consistent with Section 3(b), in the case of an Adaptation, a credit
276+ identifying the use of the Work in the Adaptation (e.g., "French
277+ translation of the Work by Original Author," or "Screenplay based on
278+ original Work by Original Author"). The credit required by this Section
279+ 4 (b) may be implemented in any reasonable manner; provided, however,
280+ that in the case of a Adaptation or Collection, at a minimum such credit
281+ will appear, if a credit for all contributing authors of the Adaptation
282+ or Collection appears, then as part of these credits and in a manner at
283+ least as prominent as the credits for the other contributing authors.
284+ For the avoidance of doubt, You may only use the credit required by this
285+ Section for the purpose of attribution in the manner set out above and,
286+ by exercising Your rights under this License, You may not implicitly or
287+ explicitly assert or imply any connection with, sponsorship or
288+ endorsement by the Original Author, Licensor and/or Attribution Parties,
289+ as appropriate, of You or Your use of the Work, without the separate,
290+ express prior written permission of the Original Author, Licensor and/or
291+ Attribution Parties.
292+ .
293+ c. Except as otherwise agreed in writing by the Licensor or as may be
294+ otherwise permitted by applicable law, if You Reproduce, Distribute or
295+ Publicly Perform the Work either by itself or as part of any Adaptations
296+ or Collections, You must not distort, mutilate, modify or take other
297+ derogatory action in relation to the Work which would be prejudicial to
298+ the Original Author's honor or reputation. Licensor agrees that in those
299+ jurisdictions (e.g. Japan), in which any exercise of the right granted
300+ in Section 3(b) of this License (the right to make Adaptations) would be
301+ deemed to be a distortion, mutilation, modification or other derogatory
302+ action prejudicial to the Original Author's honor and reputation, the
303+ Licensor will waive or not assert, as appropriate, this Section, to the
304+ fullest extent permitted by the applicable national law, to enable You
305+ to reasonably exercise Your right under Section 3(b) of this License
306+ (right to make Adaptations) but not otherwise.
307+ .
308+ 5. Representations, Warranties and Disclaimer
309+ .
310+ UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR
311+ OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY
312+ KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
313+ INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
314+ FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
315+ LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS,
316+ WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE
317+ EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.
318+ .
319+ 6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
320+ LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR
321+ ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
322+ ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS
323+ BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
324+ .
325+ 7. Termination
326+ .
327+ a. This License and the rights granted hereunder will terminate
328+ automatically upon any breach by You of the terms of this License.
329+ Individuals or entities who have received Adaptations or Collections
330+ from You under this License, however, will not have their licenses
331+ terminated provided such individuals or entities remain in full
332+ compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will
333+ survive any termination of this License.
334+ .
335+ b. Subject to the above terms and conditions, the license granted here
336+ is perpetual (for the duration of the applicable copyright in the Work).
337+ Notwithstanding the above, Licensor reserves the right to release the
338+ Work under different license terms or to stop distributing the Work at
339+ any time; provided, however that any such election will not serve to
340+ withdraw this License (or any other license that has been, or is
341+ required to be, granted under the terms of this License), and this
342+ License will continue in full force and effect unless terminated as
343+ stated above.
344+ .
345+ 8. Miscellaneous
346+ .
347+ a. Each time You Distribute or Publicly Perform the Work or a
348+ Collection, the Licensor offers to the recipient a license to the Work
349+ on the same terms and conditions as the license granted to You under
350+ this License.
351+ .
352+ b. Each time You Distribute or Publicly Perform an Adaptation, Licensor
353+ offers to the recipient a license to the original Work on the same terms
354+ and conditions as the license granted to You under this License.
355+ .
356+ c. If any provision of this License is invalid or unenforceable under
357+ applicable law, it shall not affect the validity or enforceability of
358+ the remainder of the terms of this License, and without further action
359+ by the parties to this agreement, such provision shall be reformed to
360+ the minimum extent necessary to make such provision valid and
361+ enforceable.
362+ .
363+ d. No term or provision of this License shall be deemed waived and no
364+ breach consented to unless such waiver or consent shall be in writing
365+ and signed by the party to be charged with such waiver or consent. This
366+ License constitutes the entire agreement between the parties with
367+ respect to the Work licensed here. There are no understandings,
368+ agreements or representations with respect to the Work not specified
369+ here. Licensor shall not be bound by any additional provisions that may
370+ appear in any communication from You.
371+ .
372+ e. This License may not be modified without the mutual written agreement
373+ of the Licensor and You.
374+ .
375+ f. The rights granted under, and the subject matter referenced, in this
376+ License were drafted utilizing the terminology of the Berne Convention
377+ for the Protection of Literary and Artistic Works (as amended on
378+ September 28, 1979), the Rome Convention of 1961, the WIPO Copyright
379+ Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and
380+ the Universal Copyright Convention (as revised on July 24, 1971). These
381+ rights and subject matter take effect in the relevant jurisdiction in
382+ which the License terms are sought to be enforced according to the
383+ corresponding provisions of the implementation of those treaty
384+ provisions in the applicable national law. If the standard suite of
385+ rights granted under applicable copyright law includes additional rights
386+ not granted under this License, such additional rights are deemed to be
387+ included in the License; this License is not intended to restrict the
388+ license of any rights under applicable law.
389+ .
390+ Creative Commons Notice
391+ .
392+ Creative Commons is not a party to this License, and makes no warranty
393+ whatsoever in connection with the Work. Creative Commons will not be
394+ liable to You or any party on any legal theory for any damages
395+ whatsoever, including without limitation any general, special,
396+ incidental or consequential damages arising in connection to this
397+ license. Notwithstanding the foregoing two (2) sentences, if Creative
398+ Commons has expressly identified itself as the Licensor hereunder, it
399+ shall have all rights and obligations of Licensor.
400+ .
401+ Except for the limited purpose of indicating to the public that the Work
402+ is licensed under the CCPL, Creative Commons does not authorize the use
403+ by either party of the trademark "Creative Commons" or any related
404+ trademark or logo of Creative Commons without the prior written consent
405+ of Creative Commons. Any permitted use will be in compliance with
406+ Creative Commons' then-current trademark usage guidelines, as may be
407+ published on its website or otherwise made available upon request from
408+ time to time. For the avoidance of doubt, this trademark restriction
409+ does not form part of this License.
410+ .
411+ Creative Commons may be contacted at http://creativecommons.org/.
412
413=== added file 'debian/install'
414--- debian/install 1970-01-01 00:00:00 +0000
415+++ debian/install 2013-05-01 06:18:24 +0000
416@@ -0,0 +1,17 @@
417+dropping-letters-ubuntu.qml /usr/share/dropping-letters
418+volume-sprite.png /usr/share/dropping-letters
419+test_load_binarydict.js /usr/share/dropping-letters
420+80921__justinbw__buttonchime02up.ogg /usr/share/dropping-letters
421+audio-volume-high.svg /usr/share/dropping-letters
422+music /usr/share/dropping-letters
423+redStar.png /usr/share/dropping-letters
424+audio-volume-muted.svg /usr/share/dropping-letters
425+audio-volume-high-symbolic.svg /usr/share/dropping-letters
426+45137__dj-chronos__dark-church-bell.ogg /usr/share/dropping-letters
427+106727__kantouth__cartoon-bing-low.ogg /usr/share/dropping-letters
428+audio-volume-muted-symbolic.svg /usr/share/dropping-letters
429+Easy_Lemon_60_second.ogg /usr/share/dropping-letters
430+407__tictacshutup__click-1-off-click.ogg /usr/share/dropping-letters
431+binarydict.js /usr/share/dropping-letters
432+dropping-letters.desktop /usr/share/applications
433+dropping-letters.png /usr/share/dropping-letters
434
435=== added file 'debian/rules'
436--- debian/rules 1970-01-01 00:00:00 +0000
437+++ debian/rules 2013-05-01 06:18:24 +0000
438@@ -0,0 +1,7 @@
439+#!/usr/bin/make -f
440+# -*- makefile -*-
441+# Uncomment this to turn on verbose mode.
442+#export DH_VERBOSE=1
443+
444+%:
445+ dh $@
446
447=== added directory 'debian/source'
448=== added file 'debian/source/format'
449--- debian/source/format 1970-01-01 00:00:00 +0000
450+++ debian/source/format 2013-05-01 06:18:24 +0000
451@@ -0,0 +1,1 @@
452+3.0 (native)
453
454=== renamed file 'dropping-letters-ubuntu-newui.qml' => 'dropping-letters-ubuntu.qml'
455--- dropping-letters-ubuntu-newui.qml 2013-01-25 12:25:21 +0000
456+++ dropping-letters-ubuntu.qml 2013-05-01 06:18:24 +0000
457@@ -6,617 +6,624 @@
458 import Ubuntu.Components 0.1
459 import Ubuntu.Components.Popups 0.1
460
461-Flipable {
462- id: flipable
463- property bool flipped: false
464- property variant db: null
465+MainView {
466+ id: mainView
467+ applicationName: "dropping-letters"
468 width: units.gu(45) // 48 * 7 + 2 * 7 + 2
469 height: units.gu(65) // 48 * 10 + 2 * 10 + 50
470- transform: Rotation {
471- id: rotation
472- origin.x: flipable.width/2
473- origin.y: flipable.height/2
474- axis.x: 0; axis.y: 1; axis.z: 0 // set axis.y to 1 to rotate around y-axis
475- angle: 0 // the default angle
476- }
477- property int minChromeHeight: 50
478-
479- Component.onCompleted: {
480- var db = LocalStorage.openDatabaseSync("dropping-letters", "1.0", "Dropping Letters", 1000);
481- db.transaction(function(tx) {
482- // Create the database if it doesn't already exist
483- tx.executeSql('CREATE TABLE IF NOT EXISTS Scores(score INT, time TEXT)');
484- var res = tx.executeSql('SELECT score from Scores order by score DESC LIMIT 1');
485- if (res.rows.length === 0) {
486- bestscore.updateScore(0);
487- } else {
488- bestscore.updateScore(res.rows.item(0).score);
489- }
490- });
491- }
492-
493- states: [
494- State {
495- name: "back"
496- PropertyChanges { target: rotation; angle: 180 }
497- when: flipable.flipped
498- },
499- State {
500- name: "front"
501- when: !flipable.flipped
502- }
503- ]
504-
505- transitions: [
506- Transition {
507- NumberAnimation { target: rotation; property: "angle"; duration: 200 }
508- }
509- ]
510-
511- front: Rectangle {
512- id: entry
513- color: "#efefea"
514- width: flipable.width // 48 * 7 + 2 * 7 + 2
515- height: flipable.height // 48 * 10 + 2 * 10 + 50
516-
517- Column {
518- id: logo
519- anchors.centerIn: parent
520- //spacing: units.dp(2) // 2
521- Repeater {
522- id: titleRowRepeater
523- model: ["DROP", "PING", "LETT", "ERS "]
524- Row {
525- id: titleRow
526- //spacing: units.dp(2) // 2
527- property int lineIndex: index
528- property string modelString: modelData
529- Repeater {
530- id: titleColRepeater
531- model: modelData.split("")
532- Rectangle {
533- id: titleletter
534- width: Math.max(flipable.width * 0.4, flipable.height * 0.4) / titleRowRepeater.count - titleRowRepeater.count * titleRow.spacing
535- height: Math.max(flipable.width * 0.4, flipable.height * 0.4) / titleRowRepeater.count - titleRowRepeater.count * titleRow.spacing
536- color: Qt.hsla(210/360, 0.84, 0.25 + ((4-parent.lineIndex) * 0.05) + ((4-index) * 0.05));
537- //radius: "medium"
538- Label {
539- text: modelData
540- anchors.centerIn: parent
541- fontSize: "x-large"
542- font.bold: true
543- color: "#ffffff"
544- }
545- states: [
546- State { name: "showing"; when: flipable.state == "front"
547- PropertyChanges { target: titleletter; y: 0 }
548- },
549- State { name: "notshowing"; when: flipable.state != "front"
550- PropertyChanges { target: titleletter; y: -units.gu(300) }
551- }
552- ]
553- Behavior on y {
554- SequentialAnimation {
555- PauseAnimation {
556- duration: (35 * parent.modelString.length * (4-parent.lineIndex)) + (
557- 35 * index) }
558- NumberAnimation { easing.type: Easing.OutQuart }
559- }
560- }
561- }
562- }
563- }
564- }
565- }
566- Label {
567- id: playbutton
568- text: "play"
569- anchors.top: logo.bottom
570- anchors.topMargin: units.gu(2)
571- anchors.horizontalCenter: logo.horizontalCenter
572- fontSize: "x-large"
573- color: "#222222"
574- }
575- Label {
576- id: bestscore
577- property int bestsofar: 0
578- text: "..."
579- anchors.top: playbutton.bottom
580- anchors.topMargin: units.gu(2)
581- anchors.horizontalCenter: logo.horizontalCenter
582- fontSize: "large"
583- color: "#222222"
584- function updateScore(score) {
585- if (score >= bestscore.bestsofar) {
586- bestscore.text = "Best score: " + score;
587- bestscore.bestsofar = score;
588- }
589- }
590- }
591- MouseArea {
592- anchors.fill: parent
593- enabled: !flipable.flipped
594- onClicked: {
595- lm.clear();
596- for (var i=0; i<7; i++) {
597- lm.append({'letters': [] });
598- }
599- accum.text = "";
600- droptimer.tickCount = 0;
601- flipable.flipped = true
602- }
603- }
604-
605- Rectangle {
606- id: helpbutton
607- width: units.gu(5)
608- height: units.gu(5)
609- radius: units.gu(1)
610- Label {
611- text: "?"
612- anchors.centerIn: parent
613- }
614- anchors.top: parent.top
615- anchors.right: parent.right
616- anchors.margins: units.gu(2)
617- MouseArea {
618- anchors.fill: parent
619- onClicked: {
620- PopupUtils.open(helppop, helpbutton)
621- }
622- }
623- }
624- Component {
625- id: helppop
626- Popover {
627- id: helpsheet
628- Rectangle {
629- anchors.top: parent.top
630- anchors.left: parent.left
631- anchors.right: parent.right
632- height: units.gu(15)
633- border.color: "#ddd"
634- radius: 2
635- Label {
636- anchors.fill: parent
637- anchors.margins: units.gu(1)
638- text: "game by <a href='http://twitter.com/sil'>@sil</a><br>music: <a href='http://incompetech.com/music/royalty-free/index.html?isrc=USUAN1200076'>Easy Lemon</a> from Kevin McCloud (incompetech.com)<br>sounds: freesound from <a href='http://www.freesound.org/people/kantouth/sounds/106727/'>kantouth</a> / <a href='http://www.freesound.org/people/tictacshutup/sounds/407/'>tictacshutup</a> / <a href='http://www.freesound.org/people/dj-chronos/sounds/45137/'>dj-chronos</a> / <a href='http://www.freesound.org/people/justinbw/sounds/80921/'>justinbw</a>"
639- wrapMode: Text.WordWrap
640- textFormat: Text.StyledText
641- onLinkActivated: Qt.openUrlExternally(link)
642- }
643- }
644- }
645- }
646-
647- }
648-
649- back: Rectangle {
650- id: main
651- color: "#58585A"
652- width: flipable.width // 48 * 7 + 2 * 7 + 2
653- height: flipable.height // 48 * 10 + 2 * 10 + 50
654- property var selectedItems: []
655- /*
656- obtained with:
657- import re; fp=open('/usr/share/dict/words');
658- shorts=[re.sub('[^a-zA-Z]','',x.lower().strip()) for x in fp if len(x)<7];
659- from collections import Counter; c=Counter(''.join(shorts)); least=c.most_common()[-1][1];
660- print dict([(x.upper(),c[x]/least) for x in c])
661- */
662- property variant letterFreqs: {
663- 'A': 66, 'C': 22, 'B': 19, 'E': 72, 'D': 28, 'G': 18, 'F': 12, 'I': 41, 'H': 20,
664- 'K': 14, 'J': 4, 'M': 22, 'L': 40, 'O': 48, 'N': 35, 'Q': 1, 'P': 22, 'S': 75,
665- 'R': 43, 'U': 26, 'T': 37, 'W': 13, 'V': 7, 'Y': 19, 'X': 3, 'Z': 4
666- }
667- property variant letterScores: {
668- "A":1,"B":3,"C":3,"D":2,"E":1,"F":4,"G":2,"H":4,"I":1,"J":8,"K":5,"L":1,
669- "M":3,"N":1,"O":1,"P":3,"Q":10,"R":1,"S":1,"T":1,"U":1,"V":4,"W":4,"X":8,
670- "Y":4,"Z":10
671- }
672- property int score: 0
673-
674- function getRandomWeightedLetter() {
675- // could work out sumOfWeights once, but this is easier to understand
676- var sumOfWeights = 0;
677- for (var k in main.letterFreqs) { sumOfWeights += main.letterFreqs[k]; }
678- var selection = Math.floor(Math.random() * sumOfWeights);
679- for (var k in main.letterFreqs) {
680- if (selection < main.letterFreqs[k]) return k;
681- selection -= main.letterFreqs[k];
682- }
683- }
684-
685- Audio {
686- id: music
687- source: "Easy Lemon 60 second.ogg"
688- autoPlay: true
689- onStopped: music.play()
690- muted: !volume.audible
691- }
692-
693- Audio {
694- id: click
695- source: "407__tictacshutup__click-1-off-click.ogg"
696- autoLoad: true
697- muted: !volume.audible
698- }
699-
700- Audio {
701- id: success
702- source: "80921__justinbw__buttonchime02up.ogg"
703- autoLoad: true
704- muted: !volume.audible
705- }
706-
707- Audio {
708- id: failure
709- source: "106727__kantouth__cartoon-bing-low.ogg"
710- autoLoad: true
711- muted: !volume.audible
712- }
713-
714- Audio {
715- id: gameover
716- source: "45137__dj-chronos__dark-church-bell.ogg"
717- autoLoad: true
718- onStopped: {
719- flipable.flipped = false
720- }
721- muted: !volume.audible
722- }
723-
724- Rectangle {
725- id: bottombar
726- anchors.bottom: main.bottom
727- anchors.left: main.left
728- anchors.right: main.right
729- height: (main.height - (game.squaresize * 10 + 11)) / 2
730- z: 2
731- color: Qt.hsla(210/360, 0.84, 0.2)
732-
733- Rectangle {
734- id: mainscore
735- anchors.right: quitgame.left
736- anchors.top: bottombar.top
737- anchors.bottom: bottombar.bottom
738- anchors.left: volume.right
739- z: 2
740- color: Qt.rgba(0,0,0,0)
741- Label {
742- anchors.centerIn: parent
743- fontSize: "x-large"
744- text: "" + main.score
745- color: "white"
746- }
747- }
748-
749- Rectangle {
750- id: quitgame
751- width: bottombar.height
752- height: bottombar.height
753- color: Qt.rgba(0,0,0,0)
754- anchors.right: bottombar.right
755- anchors.top: bottombar.top
756- z: 3
757-
758- Label {
759- anchors.centerIn: parent
760- text: "\u00d7"
761- fontSize: "x-large"
762- color: "white"
763- MouseArea {
764- anchors.fill: parent
765- onClicked: {
766- flipable.flipped = false;
767- }
768- }
769- }
770- }
771-
772- Rectangle {
773- id: volume
774- width: bottombar.height
775- height: bottombar.height + 1
776- color: Qt.rgba(0,0,0,0)
777- anchors.left: bottombar.left
778- anchors.bottom: bottombar.bottom
779- z: 3
780- clip: true
781- property int frame: 0
782- property bool reverse: false
783- property bool audible: true
784- Image {
785- id: image
786- sourceSize.width: parent.height * 0.8
787- sourceSize.height: parent.height * 0.8
788- anchors.centerIn: parent
789- source: volume.audible ? "audio-volume-high-symbolic.svg" : "audio-volume-muted-symbolic.svg";
790- }
791- MouseArea {
792- anchors.fill: parent
793- onClicked: {
794- volume.audible = !volume.audible
795- }
796- }
797- }
798- }
799-
800- Rectangle {
801- id: topbar
802- color: "blue"
803- anchors.top: main.top
804- anchors.left: main.left
805- anchors.right: main.right
806- height: (main.height - (game.squaresize * 10 + 11)) / 2
807- z: 2
808-
809- Rectangle {
810- anchors.fill: topbar
811- z: 2
812- color: accum.text == "" ? "#efefea" : (accum.isValid ? Qt.hsla(124/360, 0.83, 0.45) : Qt.hsla(0, 0.83, 0.65))
813- id: suggestedWordContainer
814- Label {
815- id: accum
816- anchors.centerIn: parent
817- text: ""
818- color: "white"
819- fontSize: "x-large"
820- font.bold: true
821- property bool isValid: false
822- function findBinaryWord( word ) {
823- var bd = Wordlist.wordlist;
824- var l = word.length;
825- // Don't search if there's nothing to look through
826- if ( !bd[l] ) {
827- return false;
828- }
829- // Get the number of words in the dictionary bin
830- var words = bd[l].length / l,
831- // The low point from where we're starting the binary search
832- low = 0,
833- // The max high point
834- high = words - 1,
835- // And the precise middle of the search
836- mid = Math.floor( words / 2 );
837- // We continue to look until we reach a final word
838- while ( high >= low ) {
839- // Grab the word at our current position
840- var found = bd[l].substr( l * mid, l );
841- // If we've found the word, stop now
842- if ( word === found ) {
843- return true;
844- }
845- // Otherwise, compare
846- // If we're too high, move lower
847- if ( word < found ) {
848- high = mid - 1;
849- // If we're too low, go higher
850- } else {
851- low = mid + 1;
852- }
853- // And find the new search point
854- mid = Math.floor( (low + high) / 2 );
855- }
856- // Nothing was found
857- return false;
858- }
859- onTextChanged: {
860- accum.isValid = findBinaryWord(accum.text);
861- }
862- }
863- function processSuggestedWord() {
864- if (accum.isValid) {
865- success.play();
866- var thisscore = 0, wordlength = accum.text.length;
867- accum.text = "";
868-
869- // tell the boxes to destroy themselves
870- main.selectedItems.forEach(function(b) {
871- thisscore += main.letterScores[b.containedLetter];
872- b.state = "dead";
873- })
874- main.selectedItems = [];
875- main.score += thisscore * wordlength;
876- scoredisplay.text = "" + (thisscore * wordlength);
877- showscoredisplay.start();
878- } else {
879- failure.play();
880- accum.text = "";
881- main.selectedItems.forEach(function(b) { b.selected = false; })
882- main.selectedItems = [];
883- }
884- }
885- focus: true
886- Keys.onReturnPressed: {
887- suggestedWordContainer.processSuggestedWord();
888- }
889- MouseArea {
890- anchors.fill: parent
891- onClicked: { suggestedWordContainer.processSuggestedWord(); }
892- }
893- }
894-
895-
896- }
897-
898- Label {
899- id: scoredisplay
900- anchors.centerIn: parent
901- z: 3
902- fontSize: "x-large"
903- text: "200"
904- color: "red"
905- opacity: 0
906- }
907-
908- ParallelAnimation {
909- id: showscoredisplay
910- NumberAnimation {
911- property: "scale"
912- from: 0.1
913- to: 8.0
914- duration: 400
915- target: scoredisplay
916- }
917- SequentialAnimation {
918- NumberAnimation {
919- property: "opacity"
920- from: 0
921- to: 1.0
922- duration: 20
923- target: scoredisplay
924- }
925- NumberAnimation {
926- property: "opacity"
927- from: 1.0
928- to: 0
929- duration: 380
930- target: scoredisplay
931- }
932- }
933- }
934-
935-
936- Timer {
937- id: droptimer
938- repeat: true
939- running: flipable.flipped
940- interval: 2000
941- property int tickCount: 0
942- triggeredOnStart: true
943- onTriggered: {
944- tickCount += 5
945- droptimer.interval = 2000 - tickCount
946- var idx = Math.round(Math.random() * (lm.count - 1));
947- lm.get(idx).letters.append({ letter: main.getRandomWeightedLetter() });
948- if (lm.get(idx).letters.count >= 10) {
949- droptimer.stop();
950- gameover.play();
951- var db = LocalStorage.openDatabaseSync("dropping-letters", "1.0", "Dropping Letters", 1000);
952- db.transaction(function(tx) {
953- tx.executeSql("insert into Scores values (?,?)", [main.score, 0]);
954- bestscore.updateScore(main.score);
955- });
956- }
957- }
958- }
959-
960- ListModel {
961- id: lm
962- }
963-
964-
965- Rectangle {
966- id: game
967- property int squaresize: Math.min((flipable.width) / 7, (flipable.height - (flipable.minChromeHeight * 2)) / 10)
968- anchors.top: topbar.bottom
969- anchors.bottom: bottombar.top
970- anchors.left: main.left
971- anchors.right: main.right
972- scale: -1
973+
974+ Flipable {
975+ id: flipable
976+ property bool flipped: false
977+ property variant db: null
978+ anchors.fill: parent
979+
980+ transform: Rotation {
981+ id: rotation
982+ origin.x: flipable.width/2
983+ origin.y: flipable.height/2
984+ axis.x: 0; axis.y: 1; axis.z: 0 // set axis.y to 1 to rotate around y-axis
985+ angle: 0 // the default angle
986+ }
987+ property int minChromeHeight: 50
988+
989+ Component.onCompleted: {
990+ var db = LocalStorage.openDatabaseSync("dropping-letters", "1.0", "Dropping Letters", 1000);
991+ db.transaction(function(tx) {
992+ // Create the database if it doesn't already exist
993+ tx.executeSql('CREATE TABLE IF NOT EXISTS Scores(score INT, time TEXT)');
994+ var res = tx.executeSql('SELECT score from Scores order by score DESC LIMIT 1');
995+ if (res.rows.length === 0) {
996+ bestscore.updateScore(0);
997+ } else {
998+ bestscore.updateScore(res.rows.item(0).score);
999+ }
1000+ });
1001+ }
1002+
1003+ states: [
1004+ State {
1005+ name: "back"
1006+ PropertyChanges { target: rotation; angle: 180 }
1007+ when: flipable.flipped
1008+ },
1009+ State {
1010+ name: "front"
1011+ when: !flipable.flipped
1012+ }
1013+ ]
1014+
1015+ transitions: [
1016+ Transition {
1017+ NumberAnimation { target: rotation; property: "angle"; duration: 200 }
1018+ }
1019+ ]
1020+
1021+ front: Rectangle {
1022+ id: entry
1023 color: "#efefea"
1024- Row {
1025- anchors.horizontalCenter: game.horizontalCenter
1026- anchors.top: game.top
1027- anchors.topMargin: 1
1028- //spacing: 1
1029+ width: flipable.width // 48 * 7 + 2 * 7 + 2
1030+ height: flipable.height // 48 * 10 + 2 * 10 + 50
1031+
1032+ Column {
1033+ id: logo
1034+ anchors.centerIn: parent
1035+ //spacing: units.dp(2) // 2
1036 Repeater {
1037- model: lm
1038- Column {
1039- //spacing: 1
1040- property int idx: index
1041- width: game.squaresize
1042- height: game.height
1043- add: Transition {
1044- NumberAnimation { properties: "y"; easing.type: Easing.OutBounce; duration: 1000 }
1045- }
1046- move: Transition {
1047- NumberAnimation { properties: "y"; easing.type: Easing.OutBounce }
1048- }
1049+ id: titleRowRepeater
1050+ model: ["DROP", "PING", "LETT", "ERS "]
1051+ Row {
1052+ id: titleRow
1053+ //spacing: units.dp(2) // 2
1054+ property int lineIndex: index
1055+ property string modelString: modelData
1056 Repeater {
1057- model: letters
1058+ id: titleColRepeater
1059+ model: modelData.split("")
1060 Rectangle {
1061- id: box
1062- property bool selected: false
1063- property int idx: index
1064- property string containedLetter: letter
1065- color: {
1066- if (lm.get(parent.idx).letters.count >= 10) {
1067- return "red";
1068- } else if (!selected) {
1069- return Qt.hsla(210/360, 0.84, 0.25 + (idx * 0.05));
1070- } else if (accum.isValid) {
1071- return Qt.hsla(124/360, 0.83, 0.45); // "#93cc98";
1072- } else {
1073- return Qt.hsla(0, 0.83, 0.65); // "#cc9598"
1074- }
1075- }
1076+ id: titleletter
1077+ width: Math.max(flipable.width * 0.4, flipable.height * 0.4) / titleRowRepeater.count - titleRowRepeater.count * titleRow.spacing
1078+ height: Math.max(flipable.width * 0.4, flipable.height * 0.4) / titleRowRepeater.count - titleRowRepeater.count * titleRow.spacing
1079+ color: Qt.hsla(210/360, 0.84, 0.25 + ((4-parent.lineIndex) * 0.05) + ((4-index) * 0.05));
1080 //radius: "medium"
1081- scale: -1
1082- width: game.squaresize
1083- height: game.squaresize
1084- y: game.height + game.squaresize
1085- z: 5
1086 Label {
1087+ text: modelData
1088 anchors.centerIn: parent
1089- text: letter
1090- fontSize: "large"
1091+ fontSize: "x-large"
1092 font.bold: true
1093 color: "#ffffff"
1094 }
1095- MouseArea {
1096- anchors.fill: parent
1097- onClicked: {
1098- if (!box.selected) {
1099- box.selected = true;
1100- accum.text += letter;
1101- click.play();
1102- main.selectedItems[main.selectedItems.length] = box;
1103+ states: [
1104+ State { name: "showing"; when: flipable.state == "front"
1105+ PropertyChanges { target: titleletter; y: 0 }
1106+ },
1107+ State { name: "notshowing"; when: flipable.state != "front"
1108+ PropertyChanges { target: titleletter; y: -units.gu(300) }
1109+ }
1110+ ]
1111+ Behavior on y {
1112+ SequentialAnimation {
1113+ PauseAnimation {
1114+ duration: (35 * parent.modelString.length * (4-parent.lineIndex)) + (
1115+ 35 * index) }
1116+ NumberAnimation { easing.type: Easing.OutQuart }
1117+ }
1118+ }
1119+ }
1120+ }
1121+ }
1122+ }
1123+ }
1124+ Label {
1125+ id: playbutton
1126+ text: "play"
1127+ anchors.top: logo.bottom
1128+ anchors.topMargin: units.gu(2)
1129+ anchors.horizontalCenter: logo.horizontalCenter
1130+ fontSize: "x-large"
1131+ color: "#222222"
1132+ }
1133+ Label {
1134+ id: bestscore
1135+ property int bestsofar: 0
1136+ text: "..."
1137+ anchors.top: playbutton.bottom
1138+ anchors.topMargin: units.gu(2)
1139+ anchors.horizontalCenter: logo.horizontalCenter
1140+ fontSize: "large"
1141+ color: "#222222"
1142+ function updateScore(score) {
1143+ if (score >= bestscore.bestsofar) {
1144+ bestscore.text = "Best score: " + score;
1145+ bestscore.bestsofar = score;
1146+ }
1147+ }
1148+ }
1149+ MouseArea {
1150+ anchors.fill: parent
1151+ enabled: !flipable.flipped
1152+ onClicked: {
1153+ lm.clear();
1154+ for (var i=0; i<7; i++) {
1155+ lm.append({'letters': [] });
1156+ }
1157+ accum.text = "";
1158+ droptimer.tickCount = 0;
1159+ flipable.flipped = true
1160+ }
1161+ }
1162+
1163+ Rectangle {
1164+ id: helpbutton
1165+ width: units.gu(5)
1166+ height: units.gu(5)
1167+ radius: units.gu(1)
1168+ Label {
1169+ text: "?"
1170+ anchors.centerIn: parent
1171+ }
1172+ anchors.top: parent.top
1173+ anchors.right: parent.right
1174+ anchors.margins: units.gu(2)
1175+ MouseArea {
1176+ anchors.fill: parent
1177+ onClicked: {
1178+ PopupUtils.open(helppop, helpbutton)
1179+ }
1180+ }
1181+ }
1182+ Component {
1183+ id: helppop
1184+ Popover {
1185+ id: helpsheet
1186+ Rectangle {
1187+ anchors.top: parent.top
1188+ anchors.left: parent.left
1189+ anchors.right: parent.right
1190+ height: units.gu(15)
1191+ border.color: "#ddd"
1192+ radius: 2
1193+ Label {
1194+ anchors.fill: parent
1195+ anchors.margins: units.gu(1)
1196+ text: "game by <a href='http://twitter.com/sil'>@sil</a><br>music: <a href='http://incompetech.com/music/royalty-free/index.html?isrc=USUAN1200076'>Easy Lemon</a> from Kevin McCloud (incompetech.com)<br>sounds: freesound from <a href='http://www.freesound.org/people/kantouth/sounds/106727/'>kantouth</a> / <a href='http://www.freesound.org/people/tictacshutup/sounds/407/'>tictacshutup</a> / <a href='http://www.freesound.org/people/dj-chronos/sounds/45137/'>dj-chronos</a> / <a href='http://www.freesound.org/people/justinbw/sounds/80921/'>justinbw</a>"
1197+ wrapMode: Text.WordWrap
1198+ textFormat: Text.StyledText
1199+ onLinkActivated: Qt.openUrlExternally(link)
1200+ }
1201+ }
1202+ }
1203+ }
1204+
1205+ }
1206+
1207+ back: Rectangle {
1208+ id: main
1209+ color: "#58585A"
1210+ width: flipable.width // 48 * 7 + 2 * 7 + 2
1211+ height: flipable.height // 48 * 10 + 2 * 10 + 50
1212+ property var selectedItems: []
1213+ /*
1214+ obtained with:
1215+ import re; fp=open('/usr/share/dict/words');
1216+ shorts=[re.sub('[^a-zA-Z]','',x.lower().strip()) for x in fp if len(x)<7];
1217+ from collections import Counter; c=Counter(''.join(shorts)); least=c.most_common()[-1][1];
1218+ print dict([(x.upper(),c[x]/least) for x in c])
1219+ */
1220+ property variant letterFreqs: {
1221+ 'A': 66, 'C': 22, 'B': 19, 'E': 72, 'D': 28, 'G': 18, 'F': 12, 'I': 41, 'H': 20,
1222+ 'K': 14, 'J': 4, 'M': 22, 'L': 40, 'O': 48, 'N': 35, 'Q': 1, 'P': 22, 'S': 75,
1223+ 'R': 43, 'U': 26, 'T': 37, 'W': 13, 'V': 7, 'Y': 19, 'X': 3, 'Z': 4
1224+ }
1225+ property variant letterScores: {
1226+ "A":1,"B":3,"C":3,"D":2,"E":1,"F":4,"G":2,"H":4,"I":1,"J":8,"K":5,"L":1,
1227+ "M":3,"N":1,"O":1,"P":3,"Q":10,"R":1,"S":1,"T":1,"U":1,"V":4,"W":4,"X":8,
1228+ "Y":4,"Z":10
1229+ }
1230+ property int score: 0
1231+
1232+ function getRandomWeightedLetter() {
1233+ // could work out sumOfWeights once, but this is easier to understand
1234+ var sumOfWeights = 0;
1235+ for (var k in main.letterFreqs) { sumOfWeights += main.letterFreqs[k]; }
1236+ var selection = Math.floor(Math.random() * sumOfWeights);
1237+ for (var k in main.letterFreqs) {
1238+ if (selection < main.letterFreqs[k]) return k;
1239+ selection -= main.letterFreqs[k];
1240+ }
1241+ }
1242+
1243+ Audio {
1244+ id: music
1245+ source: "Easy_Lemon_60_second.ogg"
1246+ autoPlay: true
1247+ onStopped: music.play()
1248+ muted: !volume.audible
1249+ }
1250+
1251+ Audio {
1252+ id: click
1253+ source: "407__tictacshutup__click-1-off-click.ogg"
1254+ autoLoad: true
1255+ muted: !volume.audible
1256+ }
1257+
1258+ Audio {
1259+ id: success
1260+ source: "80921__justinbw__buttonchime02up.ogg"
1261+ autoLoad: true
1262+ muted: !volume.audible
1263+ }
1264+
1265+ Audio {
1266+ id: failure
1267+ source: "106727__kantouth__cartoon-bing-low.ogg"
1268+ autoLoad: true
1269+ muted: !volume.audible
1270+ }
1271+
1272+ Audio {
1273+ id: gameover
1274+ source: "45137__dj-chronos__dark-church-bell.ogg"
1275+ autoLoad: true
1276+ onStopped: {
1277+ flipable.flipped = false
1278+ }
1279+ muted: !volume.audible
1280+ }
1281+
1282+ Rectangle {
1283+ id: bottombar
1284+ anchors.bottom: main.bottom
1285+ anchors.left: main.left
1286+ anchors.right: main.right
1287+ height: (main.height - (game.squaresize * 10 + 11)) / 2
1288+ z: 2
1289+ color: Qt.hsla(210/360, 0.84, 0.2)
1290+
1291+ Rectangle {
1292+ id: mainscore
1293+ anchors.right: quitgame.left
1294+ anchors.top: bottombar.top
1295+ anchors.bottom: bottombar.bottom
1296+ anchors.left: volume.right
1297+ z: 2
1298+ color: Qt.rgba(0,0,0,0)
1299+ Label {
1300+ anchors.centerIn: parent
1301+ fontSize: "x-large"
1302+ text: "" + main.score
1303+ color: "white"
1304+ }
1305+ }
1306+
1307+ Rectangle {
1308+ id: quitgame
1309+ width: bottombar.height
1310+ height: bottombar.height
1311+ color: Qt.rgba(0,0,0,0)
1312+ anchors.right: bottombar.right
1313+ anchors.top: bottombar.top
1314+ z: 3
1315+
1316+ Label {
1317+ anchors.centerIn: parent
1318+ text: "\u00d7"
1319+ fontSize: "x-large"
1320+ color: "white"
1321+ MouseArea {
1322+ anchors.fill: parent
1323+ onClicked: {
1324+ flipable.flipped = false;
1325+ }
1326+ }
1327+ }
1328+ }
1329+
1330+ Rectangle {
1331+ id: volume
1332+ width: bottombar.height
1333+ height: bottombar.height + 1
1334+ color: Qt.rgba(0,0,0,0)
1335+ anchors.left: bottombar.left
1336+ anchors.bottom: bottombar.bottom
1337+ z: 3
1338+ clip: true
1339+ property int frame: 0
1340+ property bool reverse: false
1341+ property bool audible: true
1342+ Image {
1343+ id: image
1344+ sourceSize.width: parent.height * 0.8
1345+ sourceSize.height: parent.height * 0.8
1346+ anchors.centerIn: parent
1347+ source: volume.audible ? "audio-volume-high-symbolic.svg" : "audio-volume-muted-symbolic.svg";
1348+ }
1349+ MouseArea {
1350+ anchors.fill: parent
1351+ onClicked: {
1352+ volume.audible = !volume.audible
1353+ }
1354+ }
1355+ }
1356+ }
1357+
1358+ Rectangle {
1359+ id: topbar
1360+ color: "blue"
1361+ anchors.top: main.top
1362+ anchors.left: main.left
1363+ anchors.right: main.right
1364+ height: (main.height - (game.squaresize * 10 + 11)) / 2
1365+ z: 2
1366+
1367+ Rectangle {
1368+ anchors.fill: topbar
1369+ z: 2
1370+ color: accum.text == "" ? "#efefea" : (accum.isValid ? Qt.hsla(124/360, 0.83, 0.45) : Qt.hsla(0, 0.83, 0.65))
1371+ id: suggestedWordContainer
1372+ Label {
1373+ id: accum
1374+ anchors.centerIn: parent
1375+ text: ""
1376+ color: "white"
1377+ fontSize: "x-large"
1378+ font.bold: true
1379+ property bool isValid: false
1380+ function findBinaryWord( word ) {
1381+ var bd = Wordlist.wordlist;
1382+ var l = word.length;
1383+ // Don't search if there's nothing to look through
1384+ if ( !bd[l] ) {
1385+ return false;
1386+ }
1387+ // Get the number of words in the dictionary bin
1388+ var words = bd[l].length / l,
1389+ // The low point from where we're starting the binary search
1390+ low = 0,
1391+ // The max high point
1392+ high = words - 1,
1393+ // And the precise middle of the search
1394+ mid = Math.floor( words / 2 );
1395+ // We continue to look until we reach a final word
1396+ while ( high >= low ) {
1397+ // Grab the word at our current position
1398+ var found = bd[l].substr( l * mid, l );
1399+ // If we've found the word, stop now
1400+ if ( word === found ) {
1401+ return true;
1402+ }
1403+ // Otherwise, compare
1404+ // If we're too high, move lower
1405+ if ( word < found ) {
1406+ high = mid - 1;
1407+ // If we're too low, go higher
1408+ } else {
1409+ low = mid + 1;
1410+ }
1411+ // And find the new search point
1412+ mid = Math.floor( (low + high) / 2 );
1413+ }
1414+ // Nothing was found
1415+ return false;
1416+ }
1417+ onTextChanged: {
1418+ accum.isValid = findBinaryWord(accum.text);
1419+ }
1420+ }
1421+ function processSuggestedWord() {
1422+ if (accum.isValid) {
1423+ success.play();
1424+ var thisscore = 0, wordlength = accum.text.length;
1425+ accum.text = "";
1426+
1427+ // tell the boxes to destroy themselves
1428+ main.selectedItems.forEach(function(b) {
1429+ thisscore += main.letterScores[b.containedLetter];
1430+ b.state = "dead";
1431+ })
1432+ main.selectedItems = [];
1433+ main.score += thisscore * wordlength;
1434+ scoredisplay.text = "" + (thisscore * wordlength);
1435+ showscoredisplay.start();
1436+ } else {
1437+ failure.play();
1438+ accum.text = "";
1439+ main.selectedItems.forEach(function(b) { b.selected = false; })
1440+ main.selectedItems = [];
1441+ }
1442+ }
1443+ focus: true
1444+ Keys.onReturnPressed: {
1445+ suggestedWordContainer.processSuggestedWord();
1446+ }
1447+ MouseArea {
1448+ anchors.fill: parent
1449+ onClicked: { suggestedWordContainer.processSuggestedWord(); }
1450+ }
1451+ }
1452+
1453+
1454+ }
1455+
1456+ Label {
1457+ id: scoredisplay
1458+ anchors.centerIn: parent
1459+ z: 3
1460+ fontSize: "x-large"
1461+ text: "200"
1462+ color: "red"
1463+ opacity: 0
1464+ }
1465+
1466+ ParallelAnimation {
1467+ id: showscoredisplay
1468+ NumberAnimation {
1469+ property: "scale"
1470+ from: 0.1
1471+ to: 8.0
1472+ duration: 400
1473+ target: scoredisplay
1474+ }
1475+ SequentialAnimation {
1476+ NumberAnimation {
1477+ property: "opacity"
1478+ from: 0
1479+ to: 1.0
1480+ duration: 20
1481+ target: scoredisplay
1482+ }
1483+ NumberAnimation {
1484+ property: "opacity"
1485+ from: 1.0
1486+ to: 0
1487+ duration: 380
1488+ target: scoredisplay
1489+ }
1490+ }
1491+ }
1492+
1493+
1494+ Timer {
1495+ id: droptimer
1496+ repeat: true
1497+ running: flipable.flipped
1498+ interval: 2000
1499+ property int tickCount: 0
1500+ triggeredOnStart: true
1501+ onTriggered: {
1502+ tickCount += 5
1503+ droptimer.interval = 2000 - tickCount
1504+ var idx = Math.round(Math.random() * (lm.count - 1));
1505+ lm.get(idx).letters.append({ letter: main.getRandomWeightedLetter() });
1506+ if (lm.get(idx).letters.count >= 10) {
1507+ droptimer.stop();
1508+ gameover.play();
1509+ var db = LocalStorage.openDatabaseSync("dropping-letters", "1.0", "Dropping Letters", 1000);
1510+ db.transaction(function(tx) {
1511+ tx.executeSql("insert into Scores values (?,?)", [main.score, 0]);
1512+ bestscore.updateScore(main.score);
1513+ });
1514+ }
1515+ }
1516+ }
1517+
1518+ ListModel {
1519+ id: lm
1520+ }
1521+
1522+
1523+ Rectangle {
1524+ id: game
1525+ property int squaresize: Math.min((flipable.width) / 7, (flipable.height - (flipable.minChromeHeight * 2)) / 10)
1526+ anchors.top: topbar.bottom
1527+ anchors.bottom: bottombar.top
1528+ anchors.left: main.left
1529+ anchors.right: main.right
1530+ scale: -1
1531+ color: "#efefea"
1532+ Row {
1533+ anchors.horizontalCenter: game.horizontalCenter
1534+ anchors.top: game.top
1535+ anchors.topMargin: 1
1536+ //spacing: 1
1537+ Repeater {
1538+ model: lm
1539+ Column {
1540+ //spacing: 1
1541+ property int idx: index
1542+ width: game.squaresize
1543+ height: game.height
1544+ add: Transition {
1545+ NumberAnimation { properties: "y"; easing.type: Easing.OutBounce; duration: 1000 }
1546+ }
1547+ move: Transition {
1548+ NumberAnimation { properties: "y"; easing.type: Easing.OutBounce }
1549+ }
1550+ Repeater {
1551+ model: letters
1552+ Rectangle {
1553+ id: box
1554+ property bool selected: false
1555+ property int idx: index
1556+ property string containedLetter: letter
1557+ color: {
1558+ if (lm.get(parent.idx).letters.count >= 10) {
1559+ return "red";
1560+ } else if (!selected) {
1561+ return Qt.hsla(210/360, 0.84, 0.25 + (idx * 0.05));
1562+ } else if (accum.isValid) {
1563+ return Qt.hsla(124/360, 0.83, 0.45); // "#93cc98";
1564 } else {
1565- if (box === main.selectedItems[main.selectedItems.length - 1]) {
1566- main.selectedItems.pop(main.selectedItems.length - 1);
1567- box.selected = false;
1568- accum.text = accum.text.substr(0, accum.text.length - 1);
1569+ return Qt.hsla(0, 0.83, 0.65); // "#cc9598"
1570+ }
1571+ }
1572+ //radius: "medium"
1573+ scale: -1
1574+ width: game.squaresize
1575+ height: game.squaresize
1576+ y: game.height + game.squaresize
1577+ z: 5
1578+ Label {
1579+ anchors.centerIn: parent
1580+ text: letter
1581+ fontSize: "large"
1582+ font.bold: true
1583+ color: "#ffffff"
1584+ }
1585+ MouseArea {
1586+ anchors.fill: parent
1587+ onClicked: {
1588+ if (!box.selected) {
1589+ box.selected = true;
1590+ accum.text += letter;
1591+ click.play();
1592+ main.selectedItems[main.selectedItems.length] = box;
1593+ } else {
1594+ if (box === main.selectedItems[main.selectedItems.length - 1]) {
1595+ main.selectedItems.pop(main.selectedItems.length - 1);
1596+ box.selected = false;
1597+ accum.text = accum.text.substr(0, accum.text.length - 1);
1598+ }
1599 }
1600 }
1601 }
1602- }
1603- Behavior on opacity {
1604- SequentialAnimation {
1605- ScriptAction { script: pulseEmitter.burst(1000); }
1606- NumberAnimation { properties:"opacity"; duration: 500 }
1607- ScriptAction { script: lm.get(box.parent.idx).letters.remove(box.idx); }
1608- }
1609- }
1610- states: [
1611- State { name: "alive" },
1612- State {
1613- name: "dead"
1614- PropertyChanges { target: box; opacity: 0 }
1615- }
1616- ]
1617- ParticleSystem {
1618- id: particles
1619- width: flipable.width / 2
1620- height: flipable.width / 2
1621- anchors.centerIn: parent
1622- clip: false
1623- ImageParticle {
1624- source: "redStar.png"
1625- alpha: 0
1626- colorVariation: 0.6
1627- }
1628- Emitter {
1629- id: pulseEmitter
1630- x: parent.width/2
1631- y: parent.height/2
1632- emitRate: 2000
1633- lifeSpan: 500
1634- enabled: false
1635- velocity: AngleDirection { magnitude: 256; angleVariation: 360; magnitudeVariation: 200; }
1636- size: parent.width / 8
1637- sizeVariation: 8
1638+ Behavior on opacity {
1639+ SequentialAnimation {
1640+ ScriptAction { script: pulseEmitter.burst(1000); }
1641+ NumberAnimation { properties:"opacity"; duration: 500 }
1642+ ScriptAction { script: lm.get(box.parent.idx).letters.remove(box.idx); }
1643+ }
1644+ }
1645+ states: [
1646+ State { name: "alive" },
1647+ State {
1648+ name: "dead"
1649+ PropertyChanges { target: box; opacity: 0 }
1650+ }
1651+ ]
1652+ ParticleSystem {
1653+ id: particles
1654+ width: flipable.width / 2
1655+ height: flipable.width / 2
1656+ anchors.centerIn: parent
1657+ clip: false
1658+ ImageParticle {
1659+ source: "redStar.png"
1660+ alpha: 0
1661+ colorVariation: 0.6
1662+ }
1663+ Emitter {
1664+ id: pulseEmitter
1665+ x: parent.width/2
1666+ y: parent.height/2
1667+ emitRate: 2000
1668+ lifeSpan: 500
1669+ enabled: false
1670+ velocity: AngleDirection { magnitude: 256; angleVariation: 360; magnitudeVariation: 200; }
1671+ size: parent.width / 8
1672+ sizeVariation: 8
1673+ }
1674 }
1675 }
1676 }
1677@@ -626,4 +633,4 @@
1678 }
1679 }
1680 }
1681-}
1682\ No newline at end of file
1683+}
1684
1685=== removed file 'dropping-letters-ubuntu.qml'
1686--- dropping-letters-ubuntu.qml 2013-01-22 00:20:27 +0000
1687+++ dropping-letters-ubuntu.qml 1970-01-01 00:00:00 +0000
1688@@ -1,602 +0,0 @@
1689-import QtQuick 2.0
1690-import QtMultimedia 5.0
1691-import "binarydict.js" as Wordlist
1692-import QtQuick.Particles 2.0
1693-import QtQuick.LocalStorage 2.0
1694-import Ubuntu.Components 0.1
1695-
1696-Flipable {
1697- id: flipable
1698- property bool flipped: false
1699- property variant db: null
1700- width: units.gu(45) // 48 * 7 + 2 * 7 + 2
1701- height: units.gu(65) // 48 * 10 + 2 * 10 + 50
1702- transform: Rotation {
1703- id: rotation
1704- origin.x: flipable.width/2
1705- origin.y: flipable.height/2
1706- axis.x: 0; axis.y: 1; axis.z: 0 // set axis.y to 1 to rotate around y-axis
1707- angle: 0 // the default angle
1708- }
1709- property int minChromeHeight: 50
1710-
1711- Component.onCompleted: {
1712- var db = LocalStorage.openDatabaseSync("dropping-letters", "1.0", "Dropping Letters", 1000);
1713- db.transaction(function(tx) {
1714- // Create the database if it doesn't already exist
1715- tx.executeSql('CREATE TABLE IF NOT EXISTS Scores(score INT, time TEXT)');
1716- var res = tx.executeSql('SELECT score from Scores order by score DESC LIMIT 1');
1717- if (res.rows.length === 0) {
1718- bestscore.updateScore(0);
1719- } else {
1720- bestscore.updateScore(res.rows.item(0).score);
1721- }
1722- });
1723- }
1724-
1725- states: [
1726- State {
1727- name: "back"
1728- PropertyChanges { target: rotation; angle: 180 }
1729- when: flipable.flipped
1730- },
1731- State {
1732- name: "front"
1733- when: !flipable.flipped
1734- }
1735- ]
1736-
1737- transitions: [
1738- Transition {
1739- NumberAnimation { target: rotation; property: "angle"; duration: 200 }
1740- }
1741- ]
1742-
1743- front: Rectangle {
1744- id: entry
1745- color: "#58585A"
1746- width: flipable.width // 48 * 7 + 2 * 7 + 2
1747- height: flipable.height // 48 * 10 + 2 * 10 + 50
1748- Column {
1749- id: logo
1750- anchors.centerIn: parent
1751- spacing: units.dp(2) // 2
1752- Repeater {
1753- id: titleRowRepeater
1754- model: ["DROP", "PING", "LETT", "ERS "]
1755- Row {
1756- id: titleRow
1757- spacing: units.dp(2) // 2
1758- property int lineIndex: index
1759- property string modelString: modelData
1760- Repeater {
1761- id: titleColRepeater
1762- model: modelData.split("")
1763- UbuntuShape {
1764- id: titleletter
1765- width: (flipable.width * 0.7) / titleRowRepeater.count - titleRowRepeater.count * titleRow.spacing
1766- height: (flipable.width * 0.7) / titleRowRepeater.count - titleRowRepeater.count * titleRow.spacing
1767- color: "#939598"
1768- radius: "medium"
1769- Label {
1770- text: modelData
1771- anchors.centerIn: parent
1772- fontSize: "large"
1773- color: "#ffffff"
1774- }
1775- states: [
1776- State { name: "showing"; when: flipable.state == "front"
1777- PropertyChanges { target: titleletter; y: 0 }
1778- },
1779- State { name: "notshowing"; when: flipable.state != "front"
1780- PropertyChanges { target: titleletter; y: -units.gu(300) }
1781- }
1782- ]
1783- Behavior on y {
1784- SequentialAnimation {
1785- PauseAnimation {
1786- duration: (35 * parent.modelString.length * (4-parent.lineIndex)) + (
1787- 35 * index) }
1788- NumberAnimation { easing.type: Easing.OutQuart }
1789- }
1790- }
1791- }
1792- }
1793- }
1794- }
1795- }
1796- Label {
1797- id: playbutton
1798- text: "play"
1799- anchors.top: logo.bottom
1800- anchors.topMargin: units.gu(2)
1801- anchors.horizontalCenter: logo.horizontalCenter
1802- fontSize: "x-large"
1803- color: "white"
1804- }
1805- Label {
1806- id: bestscore
1807- property int bestsofar: 0
1808- text: "..."
1809- anchors.top: playbutton.bottom
1810- anchors.topMargin: units.gu(2)
1811- anchors.horizontalCenter: logo.horizontalCenter
1812- fontSize: "large"
1813- color: "white"
1814- function updateScore(score) {
1815- if (score >= bestscore.bestsofar) {
1816- bestscore.text = "Best score: " + score;
1817- bestscore.bestsofar = score;
1818- }
1819- }
1820- }
1821- MouseArea {
1822- anchors.fill: parent
1823- enabled: !flipable.flipped
1824- onClicked: {
1825- lm.clear();
1826- for (var i=0; i<7; i++) {
1827- lm.append({'letters': [] });
1828- }
1829- flipable.flipped = true
1830- }
1831- }
1832- }
1833-
1834- back: Rectangle {
1835- id: main
1836- color: "#58585A"
1837- width: flipable.width // 48 * 7 + 2 * 7 + 2
1838- height: flipable.height // 48 * 10 + 2 * 10 + 50
1839- property var selectedItems: []
1840- /*
1841- obtained with:
1842- import re; fp=open('/usr/share/dict/words');
1843- shorts=[re.sub('[^a-zA-Z]','',x.lower().strip()) for x in fp if len(x)<7];
1844- from collections import Counter; c=Counter(''.join(shorts)); least=c.most_common()[-1][1];
1845- print dict([(x.upper(),c[x]/least) for x in c])
1846- */
1847- property variant letterFreqs: {
1848- 'A': 66, 'C': 22, 'B': 19, 'E': 72, 'D': 28, 'G': 18, 'F': 12, 'I': 41, 'H': 20,
1849- 'K': 14, 'J': 4, 'M': 22, 'L': 40, 'O': 48, 'N': 35, 'Q': 1, 'P': 22, 'S': 75,
1850- 'R': 43, 'U': 26, 'T': 37, 'W': 13, 'V': 7, 'Y': 19, 'X': 3, 'Z': 4
1851- }
1852- property variant letterScores: {
1853- "A":1,"B":3,"C":3,"D":2,"E":1,"F":4,"G":2,"H":4,"I":1,"J":8,"K":5,"L":1,
1854- "M":3,"N":1,"O":1,"P":3,"Q":10,"R":1,"S":1,"T":1,"U":1,"V":4,"W":4,"X":8,
1855- "Y":4,"Z":10
1856- }
1857- property int score: 0
1858-
1859- function getRandomWeightedLetter() {
1860- // could work out sumOfWeights once, but this is easier to understand
1861- var sumOfWeights = 0;
1862- for (var k in main.letterFreqs) { sumOfWeights += main.letterFreqs[k]; }
1863- var selection = Math.floor(Math.random() * sumOfWeights);
1864- for (var k in main.letterFreqs) {
1865- if (selection < main.letterFreqs[k]) return k;
1866- selection -= main.letterFreqs[k];
1867- }
1868- }
1869-
1870- Audio {
1871- id: music
1872- source: "Easy Lemon 60 second.ogg"
1873- autoPlay: true
1874- onStopped: music.play()
1875- muted: !volume.audible
1876- }
1877-
1878- Audio {
1879- id: click
1880- source: "407__tictacshutup__click-1-off-click.ogg"
1881- autoLoad: true
1882- muted: !volume.audible
1883- }
1884-
1885- Audio {
1886- id: success
1887- source: "80921__justinbw__buttonchime02up.ogg"
1888- autoLoad: true
1889- muted: !volume.audible
1890- }
1891-
1892- Audio {
1893- id: failure
1894- source: "106727__kantouth__cartoon-bing-low.ogg"
1895- autoLoad: true
1896- muted: !volume.audible
1897- }
1898-
1899- Audio {
1900- id: gameover
1901- source: "45137__dj-chronos__dark-church-bell.ogg"
1902- autoLoad: true
1903- onStopped: {
1904- flipable.flipped = false
1905- }
1906- muted: !volume.audible
1907- }
1908-
1909- Rectangle {
1910- id: bottombar
1911- color: "blue"
1912- anchors.bottom: main.bottom
1913- anchors.left: main.left
1914- anchors.right: main.right
1915- height: (main.height - (game.squaresize * 10 + 11)) / 2
1916- z: 2
1917-
1918- Rectangle {
1919- id: mainscore
1920- anchors.right: quitgame.left
1921- anchors.top: bottombar.top
1922- anchors.bottom: bottombar.bottom
1923- anchors.left: volume.right
1924- z: 2
1925- color: "#a4a4a4"
1926- Label {
1927- anchors.centerIn: parent
1928- fontSize: "x-large"
1929- text: "" + main.score
1930- color: "#222"
1931- }
1932- }
1933-
1934- Rectangle {
1935- id: quitgame
1936- width: bottombar.height
1937- height: bottombar.height
1938- color: "#a4a4a4"
1939- anchors.right: bottombar.right
1940- anchors.top: bottombar.top
1941- z: 3
1942-
1943- Label {
1944- anchors.centerIn: parent
1945- text: "x"
1946- fontSize: "x-large"
1947- color: "#222"
1948- MouseArea {
1949- anchors.fill: parent
1950- onClicked: {
1951- console.log("end game")
1952- }
1953- }
1954- }
1955- }
1956-
1957- Rectangle {
1958- id: volume
1959- width: bottombar.height
1960- height: bottombar.height
1961- color: "#a4a4a4"
1962- anchors.left: bottombar.left
1963- anchors.top: bottombar.top
1964- z: 3
1965- clip: true
1966- property int frame: 0
1967- property bool reverse: false
1968- property bool audible: true
1969- Rectangle {
1970- anchors.centerIn: parent
1971- width: image.sourceSize.height
1972- height: image.sourceSize.height
1973- color: parent.color
1974- Image {
1975- id: image
1976- source: "volume-sprite.png"
1977- x: -parent.parent.frame * parent.width
1978- }
1979- }
1980- Timer {
1981- id: volumetimer
1982- running: false
1983- interval: 10
1984- repeat: true
1985- onTriggered: {
1986- if (parent.reverse) {
1987- parent.frame -= 1;
1988- if (parent.frame == 0) volumetimer.running = false;
1989- } else {
1990- parent.frame += 1;
1991- if (parent.frame == 5) volumetimer.running = false;
1992- }
1993- }
1994- }
1995- MouseArea {
1996- anchors.fill: parent
1997- onClicked: {
1998- if (!parent.audible) {
1999- parent.frame = 5;
2000- parent.reverse = true;
2001- volumetimer.running = true;
2002- parent.audible = true;
2003- } else {
2004- parent.frame = 0;
2005- parent.reverse = false;
2006- volumetimer.running = true;
2007- parent.audible = false;
2008- }
2009- }
2010- }
2011- }
2012- }
2013-
2014- Rectangle {
2015- id: topbar
2016- color: "blue"
2017- anchors.top: main.top
2018- anchors.left: main.left
2019- anchors.right: main.right
2020- height: (main.height - (game.squaresize * 10 + 11)) / 2
2021- z: 2
2022-
2023- Rectangle {
2024- anchors.fill: topbar
2025- z: 2
2026- color: accum.text == "" ? "#a4a4a4" : (accum.isValid ? "green" : "red")
2027- Label {
2028- id: accum
2029- anchors.centerIn: parent
2030- text: ""
2031- color: "white"
2032- fontSize: "x-large"
2033- property bool isValid: false
2034- function findBinaryWord( word ) {
2035- var bd = Wordlist.wordlist;
2036- var l = word.length;
2037- // Don't search if there's nothing to look through
2038- if ( !bd[l] ) {
2039- return false;
2040- }
2041- // Get the number of words in the dictionary bin
2042- var words = bd[l].length / l,
2043- // The low point from where we're starting the binary search
2044- low = 0,
2045- // The max high point
2046- high = words - 1,
2047- // And the precise middle of the search
2048- mid = Math.floor( words / 2 );
2049- // We continue to look until we reach a final word
2050- while ( high >= low ) {
2051- // Grab the word at our current position
2052- var found = bd[l].substr( l * mid, l );
2053- // If we've found the word, stop now
2054- if ( word === found ) {
2055- return true;
2056- }
2057- // Otherwise, compare
2058- // If we're too high, move lower
2059- if ( word < found ) {
2060- high = mid - 1;
2061- // If we're too low, go higher
2062- } else {
2063- low = mid + 1;
2064- }
2065- // And find the new search point
2066- mid = Math.floor( (low + high) / 2 );
2067- }
2068- // Nothing was found
2069- return false;
2070- }
2071- onTextChanged: {
2072- accum.isValid = findBinaryWord(accum.text);
2073- }
2074- }
2075- MouseArea {
2076- anchors.fill: parent
2077- onClicked: {
2078- if (accum.isValid) {
2079- success.play();
2080- var thisscore = 0, wordlength = accum.text.length;
2081- accum.text = "";
2082-
2083- // tell the boxes to destroy themselves
2084- main.selectedItems.forEach(function(b) {
2085- thisscore += main.letterScores[b.containedLetter];
2086- b.state = "dead";
2087- })
2088- main.selectedItems = [];
2089- main.score += thisscore * wordlength;
2090- scoredisplay.text = "" + (thisscore * wordlength);
2091- showscoredisplay.start();
2092- } else {
2093- failure.play();
2094- accum.text = "";
2095- main.selectedItems.forEach(function(b) { b.selected = false; })
2096- main.selectedItems = [];
2097- }
2098- }
2099- }
2100- }
2101-
2102-
2103- }
2104-
2105- Label {
2106- id: scoredisplay
2107- anchors.centerIn: parent
2108- z: 3
2109- fontSize: "x-large"
2110- text: "200"
2111- color: "red"
2112- opacity: 0
2113- }
2114-
2115- ParallelAnimation {
2116- id: showscoredisplay
2117- NumberAnimation {
2118- property: "scale"
2119- from: 0.1
2120- to: 8.0
2121- duration: 400
2122- target: scoredisplay
2123- }
2124- SequentialAnimation {
2125- NumberAnimation {
2126- property: "opacity"
2127- from: 0
2128- to: 1.0
2129- duration: 20
2130- target: scoredisplay
2131- }
2132- NumberAnimation {
2133- property: "opacity"
2134- from: 1.0
2135- to: 0
2136- duration: 380
2137- target: scoredisplay
2138- }
2139- }
2140- }
2141-
2142-
2143- Timer {
2144- id: droptimer
2145- repeat: true
2146- running: flipable.flipped
2147- interval: 2000
2148- property int tickCount: 0
2149- triggeredOnStart: true
2150- onTriggered: {
2151- tickCount += 10
2152- droptimer.interval = 2000 - tickCount
2153- var idx = Math.round(Math.random() * (lm.count - 1));
2154- lm.get(idx).letters.append({ letter: main.getRandomWeightedLetter() });
2155- if (lm.get(idx).letters.count >= 10) {
2156- droptimer.stop();
2157- gameover.play();
2158- var db = LocalStorage.openDatabaseSync("dropping-letters", "1.0", "Dropping Letters", 1000);
2159- db.transaction(function(tx) {
2160- tx.executeSql("insert into Scores values (?,?)", [main.score, 0]);
2161- bestscore.updateScore(main.score);
2162- });
2163- }
2164- }
2165- }
2166-
2167- ListModel {
2168- id: lm
2169- }
2170-
2171-
2172- Rectangle {
2173- id: game
2174- property int squaresize: Math.min((flipable.width - 8) / 7, (flipable.height - (flipable.minChromeHeight * 2) - 11) / 10)
2175- anchors.top: topbar.bottom
2176- anchors.bottom: bottombar.top
2177- anchors.left: main.left
2178- anchors.right: main.right
2179- scale: -1
2180- color: "#444"
2181- Row {
2182- anchors.horizontalCenter: game.horizontalCenter
2183- anchors.top: game.top
2184- anchors.topMargin: 1
2185- spacing: 1
2186- Repeater {
2187- model: lm
2188- Column {
2189- spacing: 1
2190- property int idx: index
2191- width: game.squaresize
2192- height: game.height
2193- add: Transition {
2194- NumberAnimation { properties: "y"; easing.type: Easing.OutBounce; duration: 1000 }
2195- }
2196- move: Transition {
2197- NumberAnimation { properties: "y"; easing.type: Easing.OutBounce }
2198- }
2199- Repeater {
2200- model: letters
2201- UbuntuShape {
2202- id: box
2203- property bool selected: false
2204- property int idx: index
2205- property string containedLetter: letter
2206- color: {
2207- if (lm.get(parent.idx).letters.count >= 10) {
2208- return "red";
2209- } else if (!selected) {
2210- return "#939598";
2211- } else if (accum.isValid) {
2212- return "#93cc98";
2213- } else {
2214- return "#cc9598"
2215- }
2216- }
2217- radius: "medium"
2218- scale: -1
2219- width: game.squaresize
2220- height: game.squaresize
2221- y: game.height + game.squaresize
2222- z: 5
2223- Label {
2224- anchors.centerIn: parent
2225- text: letter
2226- fontSize: "large"
2227- color: "#ffffff"
2228- }
2229- MouseArea {
2230- anchors.fill: parent
2231- onClicked: {
2232- if (!box.selected) {
2233- box.selected = true;
2234- accum.text += letter;
2235- click.play();
2236- main.selectedItems[main.selectedItems.length] = box;
2237- } else {
2238- if (box === main.selectedItems[main.selectedItems.length - 1]) {
2239- main.selectedItems.pop(main.selectedItems.length - 1);
2240- box.selected = false;
2241- accum.text = accum.text.substr(0, accum.text.length - 1);
2242- }
2243- }
2244- }
2245- }
2246- Behavior on opacity {
2247- SequentialAnimation {
2248- ScriptAction { script: pulseEmitter.burst(1000); }
2249- NumberAnimation { properties:"opacity"; duration: 500 }
2250- ScriptAction { script: lm.get(box.parent.idx).letters.remove(box.idx); }
2251- }
2252- }
2253- states: [
2254- State { name: "alive" },
2255- State {
2256- name: "dead"
2257- PropertyChanges { target: box; opacity: 0 }
2258- }
2259- ]
2260- ParticleSystem {
2261- id: particles
2262- width: flipable.width / 2
2263- height: flipable.width / 2
2264- anchors.centerIn: parent
2265- clip: false
2266- ImageParticle {
2267- source: "redStar.png"
2268- alpha: 0
2269- colorVariation: 0.6
2270- }
2271- Emitter {
2272- id: pulseEmitter
2273- x: parent.width/2
2274- y: parent.height/2
2275- emitRate: 2000
2276- lifeSpan: 500
2277- enabled: false
2278- velocity: AngleDirection { magnitude: 256; angleVariation: 360; magnitudeVariation: 200; }
2279- size: parent.width / 8
2280- sizeVariation: 8
2281- }
2282- }
2283- }
2284- }
2285- }
2286- }
2287- }
2288- }
2289- }
2290-}
2291\ No newline at end of file
2292
2293=== added file 'dropping-letters.desktop'
2294--- dropping-letters.desktop 1970-01-01 00:00:00 +0000
2295+++ dropping-letters.desktop 2013-05-01 06:18:24 +0000
2296@@ -0,0 +1,11 @@
2297+[Desktop Entry]
2298+Encoding=UTF-8
2299+Version=1.0
2300+Type=Application
2301+Icon=/usr/share/dropping-letters/dropping-letters.png
2302+Terminal=false
2303+Name=Dropping Letters
2304+Exec=qmlscene /usr/share/dropping-letters/dropping-letters-ubuntu.qml
2305+X-Ubuntu-Touch=true
2306+X-Ubuntu-StageHint=SideStage
2307+
2308
2309=== added file 'dropping-letters.png'
2310Binary files dropping-letters.png 1970-01-01 00:00:00 +0000 and dropping-letters.png 2013-05-01 06:18:24 +0000 differ
2311=== removed file 'dropping-letters.qml'
2312--- dropping-letters.qml 2013-01-11 17:26:38 +0000
2313+++ dropping-letters.qml 1970-01-01 00:00:00 +0000
2314@@ -1,546 +0,0 @@
2315-import QtQuick 2.0
2316-import QtMultimedia 5.0
2317-import "binarydict.js" as Wordlist
2318-import QtQuick.Particles 2.0
2319-import QtQuick.LocalStorage 2.0
2320-
2321-Flipable {
2322- id: flipable
2323- property bool flipped: false
2324- property variant db: null
2325- width: 48 * 7 + 2 * 7 + 2
2326- height: 48 * 10 + 2 * 10 + 50
2327- transform: Rotation {
2328- id: rotation
2329- origin.x: flipable.width/2
2330- origin.y: flipable.height/2
2331- axis.x: 0; axis.y: 1; axis.z: 0 // set axis.y to 1 to rotate around y-axis
2332- angle: 0 // the default angle
2333- }
2334-
2335- Component.onCompleted: {
2336- var db = LocalStorage.openDatabaseSync("dropping-letters", "1.0", "Dropping Letters", 1000);
2337- db.transaction(function(tx) {
2338- // Create the database if it doesn't already exist
2339- tx.executeSql('CREATE TABLE IF NOT EXISTS Scores(score INT, time TEXT)');
2340- var res = tx.executeSql('SELECT score from Scores order by score DESC LIMIT 1');
2341- if (res.rows.length === 0) {
2342- bestscore.updateScore(0);
2343- } else {
2344- bestscore.updateScore(res.rows.item(0).score);
2345- }
2346- });
2347- }
2348-
2349- states: [
2350- State {
2351- name: "back"
2352- PropertyChanges { target: rotation; angle: 180 }
2353- when: flipable.flipped
2354- },
2355- State {
2356- name: "front"
2357- when: !flipable.flipped
2358- }
2359- ]
2360-
2361- transitions: [
2362- Transition {
2363- NumberAnimation { target: rotation; property: "angle"; duration: 200 }
2364- }
2365- ]
2366-
2367- front: Rectangle {
2368- id: entry
2369- color: "#58585A"
2370- width: 48 * 7 + 2 * 7 + 2
2371- height: 48 * 10 + 2 * 10 + 50
2372- Column {
2373- id: logo
2374- anchors.centerIn: parent
2375- spacing: 2
2376- Repeater {
2377- model: ["DROP", "PING", "LETT", "ERS "]
2378- Row {
2379- spacing: 2
2380- property int lineIndex: index
2381- property string modelString: modelData
2382- Repeater {
2383- model: modelData.split("")
2384- Rectangle {
2385- id: titleletter
2386- width: 50
2387- height: 50
2388- color: "#939598"
2389- radius: 3
2390- Text {
2391- text: modelData
2392- anchors.centerIn: parent
2393- font.pixelSize: titleletter.height * 0.6
2394- color: "#ffffff"
2395- font.family: "Helvetica"
2396- }
2397- states: [
2398- State { name: "showing"; when: flipable.state == "front"
2399- PropertyChanges { target: titleletter; y: 0 }
2400- },
2401- State { name: "notshowing"; when: flipable.state != "front"
2402- PropertyChanges { target: titleletter; y: -500 }
2403- }
2404- ]
2405- Behavior on y {
2406- SequentialAnimation {
2407- PauseAnimation {
2408- duration: (35 * parent.modelString.length * (4-parent.lineIndex)) + (
2409- 35 * index) }
2410- NumberAnimation { easing.type: Easing.OutQuart }
2411- }
2412- }
2413- }
2414- }
2415- }
2416- }
2417- }
2418- Text {
2419- id: playbutton
2420- text: "play"
2421- anchors.top: logo.bottom
2422- anchors.topMargin: 15
2423- anchors.horizontalCenter: logo.horizontalCenter
2424- font.pixelSize: 30
2425- color: "white"
2426- }
2427- Text {
2428- id: bestscore
2429- property int bestsofar: 0
2430- text: "..."
2431- anchors.top: playbutton.bottom
2432- anchors.topMargin: 15
2433- anchors.horizontalCenter: logo.horizontalCenter
2434- font.pixelSize: 30
2435- color: "white"
2436- function updateScore(score) {
2437- if (score >= bestscore.bestsofar) {
2438- bestscore.text = "Best score: " + score;
2439- bestscore.bestsofar = score;
2440- }
2441- }
2442- }
2443- MouseArea {
2444- anchors.fill: parent
2445- enabled: !flipable.flipped
2446- onClicked: {
2447- lm.clear();
2448- for (var i=0; i<7; i++) {
2449- lm.append({'letters': [] });
2450- }
2451- flipable.flipped = true
2452- }
2453- }
2454- }
2455-
2456- back: Rectangle {
2457- id: main
2458- color: "#58585A"
2459- width: 48 * 7 + 2 * 7 + 2
2460- height: 48 * 10 + 2 * 10 + 50
2461- property var selectedItems: []
2462- /*
2463- obtained with:
2464- import re; fp=open('/usr/share/dict/words');
2465- shorts=[re.sub('[^a-zA-Z]','',x.lower().strip()) for x in fp if len(x)<7];
2466- from collections import Counter; c=Counter(''.join(shorts)); least=c.most_common()[-1][1];
2467- print dict([(x.upper(),c[x]/least) for x in c])
2468- */
2469- property variant letterFreqs: {
2470- 'A': 66, 'C': 22, 'B': 19, 'E': 72, 'D': 28, 'G': 18, 'F': 12, 'I': 41, 'H': 20,
2471- 'K': 14, 'J': 4, 'M': 22, 'L': 40, 'O': 48, 'N': 35, 'Q': 1, 'P': 22, 'S': 75,
2472- 'R': 43, 'U': 26, 'T': 37, 'W': 13, 'V': 7, 'Y': 19, 'X': 3, 'Z': 4
2473- }
2474- property variant letterScores: {
2475- "A":1,"B":3,"C":3,"D":2,"E":1,"F":4,"G":2,"H":4,"I":1,"J":8,"K":5,"L":1,
2476- "M":3,"N":1,"O":1,"P":3,"Q":10,"R":1,"S":1,"T":1,"U":1,"V":4,"W":4,"X":8,
2477- "Y":4,"Z":10
2478- }
2479- property int score: 0
2480-
2481- function getRandomWeightedLetter() {
2482- // could work out sumOfWeights once, but this is easier to understand
2483- var sumOfWeights = 0;
2484- for (var k in main.letterFreqs) { sumOfWeights += main.letterFreqs[k]; }
2485- var selection = Math.floor(Math.random() * sumOfWeights);
2486- for (var k in main.letterFreqs) {
2487- if (selection < main.letterFreqs[k]) return k;
2488- selection -= main.letterFreqs[k];
2489- }
2490- }
2491-
2492- Audio {
2493- id: music
2494- source: "Easy Lemon 60 second.ogg"
2495- autoPlay: true
2496- onStopped: music.play()
2497- muted: !volume.audible
2498- }
2499-
2500- Audio {
2501- id: click
2502- source: "407__tictacshutup__click-1-off-click.ogg"
2503- autoLoad: true
2504- muted: !volume.audible
2505- }
2506-
2507- Audio {
2508- id: success
2509- source: "80921__justinbw__buttonchime02up.ogg"
2510- autoLoad: true
2511- muted: !volume.audible
2512- }
2513-
2514- Audio {
2515- id: failure
2516- source: "106727__kantouth__cartoon-bing-low.ogg"
2517- autoLoad: true
2518- muted: !volume.audible
2519- }
2520-
2521- Audio {
2522- id: gameover
2523- source: "45137__dj-chronos__dark-church-bell.ogg"
2524- autoLoad: true
2525- onStopped: {
2526- flipable.flipped = false
2527- }
2528- muted: !volume.audible
2529- }
2530-
2531-
2532- Rectangle {
2533- id: volume
2534- width: 48
2535- height: 48
2536- color: "#a4a4a4"
2537- anchors.left: main.left
2538- anchors.top: main.top
2539- z: 2
2540- clip: true
2541- property int frame: 0
2542- property bool reverse: false
2543- property bool audible: true
2544- Image {
2545- id: image
2546- source: "volume-sprite.png"
2547- x: -parent.frame * parent.width
2548- }
2549- Timer {
2550- id: volumetimer
2551- running: false
2552- interval: 10
2553- repeat: true
2554- onTriggered: {
2555- if (parent.reverse) {
2556- parent.frame -= 1;
2557- if (parent.frame == 0) volumetimer.running = false;
2558- } else {
2559- parent.frame += 1;
2560- if (parent.frame == 5) volumetimer.running = false;
2561- }
2562- }
2563- }
2564- MouseArea {
2565- anchors.fill: parent
2566- onClicked: {
2567- if (!parent.audible) {
2568- parent.frame = 5;
2569- parent.reverse = true;
2570- volumetimer.running = true;
2571- parent.audible = true;
2572- } else {
2573- parent.frame = 0;
2574- parent.reverse = false;
2575- volumetimer.running = true;
2576- parent.audible = false;
2577- }
2578- }
2579- }
2580- }
2581-
2582- Text {
2583- id: scoredisplay
2584- anchors.centerIn: parent
2585- z: 3
2586- font.pixelSize: main.height
2587- text: "200"
2588- color: "red"
2589- opacity: 0
2590- }
2591-
2592- Rectangle {
2593- id: mainscore
2594- anchors.right: main.right
2595- anchors.top: main.top
2596- width: 50
2597- height: 48
2598- z: 2
2599- color: "#a4a4a4"
2600- Text {
2601- anchors.centerIn: parent
2602- font.pixelSize: 50/3
2603- text: "" + main.score
2604- color: "#222"
2605- }
2606- }
2607-
2608- ParallelAnimation {
2609- id: showscoredisplay
2610- NumberAnimation {
2611- property: "scale"
2612- from: 0.01
2613- to: 1.0
2614- duration: 400
2615- target: scoredisplay
2616- }
2617- SequentialAnimation {
2618- NumberAnimation {
2619- property: "opacity"
2620- from: 0
2621- to: 1.0
2622- duration: 20
2623- target: scoredisplay
2624- }
2625- NumberAnimation {
2626- property: "opacity"
2627- from: 1.0
2628- to: 0
2629- duration: 380
2630- target: scoredisplay
2631- }
2632- }
2633- }
2634-
2635-
2636-
2637- Timer {
2638- id: droptimer
2639- repeat: true
2640- running: flipable.flipped
2641- interval: 2000
2642- triggeredOnStart: true
2643- onTriggered: {
2644- var idx = Math.round(Math.random() * (lm.count - 1));
2645- lm.get(idx).letters.append({ letter: main.getRandomWeightedLetter() });
2646- if (lm.get(idx).letters.count >= 10) {
2647- droptimer.stop();
2648- gameover.play();
2649- var db = LocalStorage.openDatabaseSync("dropping-letters", "1.0", "Dropping Letters", 1000);
2650- db.transaction(function(tx) {
2651- tx.executeSql("insert into Scores values (?,?)", [main.score, 0]);
2652- bestscore.updateScore(main.score);
2653- });
2654- }
2655- }
2656- }
2657-
2658- ListModel {
2659- id: lm
2660- }
2661-
2662- Rectangle {
2663- anchors.top: main.top
2664- anchors.left: main.left
2665- anchors.right: playarea.right
2666- anchors.bottom: playarea.top
2667- anchors.rightMargin: 50
2668- anchors.leftMargin: 50
2669- anchors.bottomMargin: 2
2670- z: 2
2671- color: accum.text == "" ? "#a4a4a4" : (accum.isValid ? "green" : "red")
2672- Text {
2673- id: accum
2674- anchors.centerIn: parent
2675- text: ""
2676- color: "white"
2677- font.pixelSize: parent.height * 0.7
2678- font.family: "Helvetica"
2679- property bool isValid: false
2680- function findBinaryWord( word ) {
2681- var bd = Wordlist.wordlist;
2682- var l = word.length;
2683- // Don't search if there's nothing to look through
2684- if ( !bd[l] ) {
2685- return false;
2686- }
2687- // Get the number of words in the dictionary bin
2688- var words = bd[l].length / l,
2689- // The low point from where we're starting the binary search
2690- low = 0,
2691- // The max high point
2692- high = words - 1,
2693- // And the precise middle of the search
2694- mid = Math.floor( words / 2 );
2695- // We continue to look until we reach a final word
2696- while ( high >= low ) {
2697- // Grab the word at our current position
2698- var found = bd[l].substr( l * mid, l );
2699- // If we've found the word, stop now
2700- if ( word === found ) {
2701- return true;
2702- }
2703- // Otherwise, compare
2704- // If we're too high, move lower
2705- if ( word < found ) {
2706- high = mid - 1;
2707- // If we're too low, go higher
2708- } else {
2709- low = mid + 1;
2710- }
2711- // And find the new search point
2712- mid = Math.floor( (low + high) / 2 );
2713- }
2714- // Nothing was found
2715- return false;
2716- }
2717- onTextChanged: {
2718- accum.isValid = findBinaryWord(accum.text);
2719- }
2720- }
2721- MouseArea {
2722- anchors.fill: parent
2723- onClicked: {
2724- if (accum.isValid) {
2725- success.play();
2726- var thisscore = 0, wordlength = accum.text.length;
2727- accum.text = "";
2728-
2729- // tell the boxes to destroy themselves
2730- main.selectedItems.forEach(function(b) {
2731- thisscore += main.letterScores[b.containedLetter];
2732- b.state = "dead";
2733- })
2734- main.selectedItems = [];
2735- main.score += thisscore * wordlength;
2736- scoredisplay.text = "" + (thisscore * wordlength);
2737- showscoredisplay.start();
2738- } else {
2739- failure.play();
2740- accum.text = "";
2741- main.selectedItems.forEach(function(b) { b.selected = false; })
2742- main.selectedItems = [];
2743- }
2744- }
2745- }
2746- }
2747-
2748- Row {
2749- id: playarea
2750- anchors.top: main.top
2751- anchors.topMargin: 50
2752- anchors.left: main.left
2753- anchors.leftMargin: 2
2754- spacing: 2
2755- Repeater {
2756- model: lm
2757- Column {
2758- add: Transition {
2759- NumberAnimation { properties: "y"; easing.type: Easing.OutBounce; duration: 1000 }
2760- }
2761- move: Transition {
2762- NumberAnimation { properties: "y"; easing.type: Easing.OutBounce }
2763- }
2764- property int idx: index
2765- width: 48
2766- height: main.height - 52
2767- scale: -1
2768- spacing: 2
2769- Repeater {
2770- model: letters
2771- Rectangle {
2772- property bool selected: false
2773- property int idx: index
2774- property string containedLetter: letter
2775- id: box
2776- clip: false
2777- scale: -1
2778- width: 48
2779- height: 48
2780- color: {
2781- if (lm.get(parent.idx).letters.count >= 10) {
2782- return "red";
2783- } else if (!selected) {
2784- return "#939598";
2785- } else if (accum.isValid) {
2786- return "#93cc98";
2787- } else {
2788- return "#cc9598"
2789- }
2790- }
2791- radius: 3
2792- y: main.height + box.height
2793- Text {
2794- anchors.centerIn: parent
2795- text: letter
2796- font.pixelSize: box.height * 0.6
2797- color: "#ffffff"
2798- font.family: "Helvetica"
2799- }
2800- MouseArea {
2801- anchors.fill: parent
2802- onClicked: {
2803- if (!box.selected) {
2804- box.selected = true;
2805- accum.text += letter;
2806- click.play();
2807- main.selectedItems[main.selectedItems.length] = box;
2808- } else {
2809- if (box === main.selectedItems[main.selectedItems.length - 1]) {
2810- main.selectedItems.pop(main.selectedItems.length - 1);
2811- box.selected = false;
2812- accum.text = accum.text.substr(0, accum.text.length - 1);
2813- }
2814- }
2815- }
2816- }
2817- Behavior on opacity {
2818- SequentialAnimation {
2819- ScriptAction { script: pulseEmitter.burst(1000); }
2820- NumberAnimation { properties:"opacity"; duration: 500 }
2821- ScriptAction { script: lm.get(box.parent.idx).letters.remove(box.idx); }
2822- }
2823- }
2824- states: [
2825- State { name: "alive" },
2826- State {
2827- name: "dead"
2828- PropertyChanges { target: box; opacity: 0 }
2829- }
2830- ]
2831- ParticleSystem {
2832- id: particles
2833- width: 200
2834- height: 200
2835- anchors.centerIn: parent
2836- clip: false
2837- ImageParticle {
2838- source: "redStar.png"
2839- alpha: 0
2840- colorVariation: 0.6
2841- }
2842- Emitter {
2843- id: pulseEmitter
2844- x: parent.width/2
2845- y: parent.height/2
2846- emitRate: 2000
2847- lifeSpan: 500
2848- enabled: false
2849- velocity: AngleDirection { magnitude: 256; angleVariation: 360; magnitudeVariation: 200; }
2850- size: 32
2851- sizeVariation: 8
2852- }
2853- }
2854- }
2855- }
2856- }
2857- }
2858- }
2859- }
2860-}
2861\ No newline at end of file
2862
2863=== added file 'dropping-letters.qmlproject'
2864--- dropping-letters.qmlproject 1970-01-01 00:00:00 +0000
2865+++ dropping-letters.qmlproject 2013-05-01 06:18:24 +0000
2866@@ -0,0 +1,31 @@
2867+/* File generated by Qt Creator (with Ubuntu Plugin), version 2.7.0 */
2868+
2869+import QmlProject 1.1
2870+
2871+Project {
2872+ mainFile: "dropping-letters-ubuntu.qml"
2873+
2874+ /* Include .qml, .js, and image files from current directory and subdirectories */
2875+ QmlFiles {
2876+ directory: "."
2877+ }
2878+ JavaScriptFiles {
2879+ directory: "."
2880+ }
2881+ ImageFiles {
2882+ directory: "."
2883+ }
2884+ Files {
2885+ filter: "*.desktop"
2886+ }
2887+ Files {
2888+ directory: "html"
2889+ filter: "*"
2890+ }
2891+ Files {
2892+ directory: "debian"
2893+ filter: "*"
2894+ }
2895+ /* List of plugin directories passed to QML runtime */
2896+ importPaths: [ "." ,"/usr/bin","/usr/lib/x86_64-linux-gnu/qt5/qml" ]
2897+}

Subscribers

People subscribed via source and target branches