Skip to content

Instantly share code, notes, and snippets.

@TatsuoWatanabe
Last active February 12, 2017 13:12
Show Gist options
  • Save TatsuoWatanabe/2d369f739348e45da3aaa393821c3dab to your computer and use it in GitHub Desktop.
Save TatsuoWatanabe/2d369f739348e45da3aaa393821c3dab to your computer and use it in GitHub Desktop.
A song of "Grandfather's Clock" as a javascript source code.
/***************************************************************************
Copyright (c) 2017 tatsuo watanabe<tatsuo1234567@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
****************************************************************************/
/**
* Tick the lifetime
*/
class TickTockable {
constructor(opts) {
const options = opts || {};
this.duration = options.duration || 1000;
this.narrator = options.narrator || console.log;
this.age = 0;
this.isBorn = false;
this.isAlive = true;
this.promise = new Promise((resolve) => { this.resolve = resolve; });
}
/** Tick the time. */
tick() { this.alive(() => this.tock()); const s = this.sound('tick'); if (!s) { return; } this.narrator(s); }
/** Tock the time. */
tock() { this.alive(() => this.tick()); const s = this.sound('tock'); if (!s) { return; } this.narrator(s); }
/** Variety of somethig will affair. */
affair() { this.narrator('Variety of somethig will affair.'); }
/** There are many things if you live. */
alive(callback) {
if (!this.isAlive) { return; }
if (this.isBorn) { this.age += 1; }
this.affair();
setTimeout(() => {
callback();
}, this.duration);
}
/** Sounds of your story. */
sound(key) {
const sounds = { tick: 'tick...', tock: 'tock...' };
return sounds[key];
}
rnd(accuracy) {
return Math.ceil(Math.random() * accuracy) === accuracy;
}
}
class Oldman extends TickTockable {
constructor(clock, opts, name) {
super(opts);
this.name = name;
this.clock = clock;
this.isBorn = false;
this.alive(() => this.tick());
}
sound() {
const footstep = !this.isBorn ? 'throb...' :
this.age < 3 ? 'mewl...' :
this.age === 13 ? 'giggle...' :
this.age === 17 ? 'yeah...' :
this.age === 24 ? 'you are my pleasure...' :
this.age === 75 ? 'what a faithful clock...' :
'';
return footstep;
}
affair() {
this.born();
this.marry();
this.babyBorn();
this.grandChildBorn();
this.die();
}
born() {
if (this.isBorn) { return; }
if (!this.rnd(10)) { return; }
this.isBorn = true;
this.clock.owner = this;
this.narrator(`${this.name} was born.`);
}
marry() {
if (this.age !== 24 || this.married) { return; }
this.married = true;
this.narrator(`Blooming and beautiful bride came.`);
}
babyBorn() {
if (this.age !== 30 || this.hasChild) { return; }
this.hasChild = true;
this.narrator(`${this.name} had a baby born.`);
}
grandChildBorn() {
if (this.age !== 60 || this.hasGrandchild) { return; }
this.hasGrandchild = true;
this.narrator(
`${this.name} had a grandchild born.\nI was born.`
);
}
die() {
if (this.age < 90) { return; }
this.isAlive = false;
setTimeout(() => {
this.narrator(`${this.name} was died.`);
this.resolve();
}, this.duration * 2);
}
}
class Clock extends TickTockable {
constructor(opts) {
super(opts);
this.isBorn = true;
this.isBought = false;
this.owner = undefined;
this.alive(() => this.tick());
}
affair() {
this.bought();
this.die();
}
bought() {
if (!this.owner || this.isBought) { return; }
this.isBought = true;
this.narrator(`The clock was bought for ${this.owner.name}.` );
}
die() {
if (!this.owner || this.owner.isAlive) { return; }
this.isAlive = false;
setTimeout(() => {
this.narrator(`The clock stopped short, never to go again.`);
this.resolve();
}, this.duration * 2);
}
}
/**
* "Grandfather's Clock" is a song written in 1876 by Henry Clay Work,
* the author of "Marching Through Georgia".
* It is a standard of British brass bands and colliery bands,
* and is also popular in bluegrass music.
* It has also been sung by male choruses such as the Robert Shaw Chorale.
* --- From Wikipedia, the free encyclopedia
*
* @see https://en.wikipedia.org/wiki/My_Grandfather's_Clock
*/
function myGrandfathersClock(opts) {
const options = opts || {};
options.narrator = options.narrator || console.log;
options.duration = options.duration || 1000;
const narrator = options.narrator;
const clock = new Clock(options);
const grandfather = new Oldman(clock, options, 'My grandfather');
Promise.all([
clock.promise,
grandfather.promise
]).then(() =>
setTimeout(() => narrator('I remember you.'), options.duration)
);
}
myGrandfathersClock();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment