Skip to content

Commit 3f64f98

Browse files
committed
Reorganize the codebase in class files :)
1 parent dfbfd0f commit 3f64f98

11 files changed

+300
-81
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
node_modules
2-
.tsbuildinfo
2+
*.tsbuildinfo
3+
build/*.tsbuildinfo

assets/bootstrap.min.css

-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

assets/bootstrap.min.js

-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

assets/popper.min.js

-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build/index.js

+177-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,177 @@
1-
var HandpanHit=function(){function a(t,e,n){if(!a.isValidHitType(t))throw"Invalid hit type";this.type=t}return a.isValidHitType=function(e){return 0<this.types.filter(function(t){return t.type===e}).length},a.getRandomHit=function(){return this.types[Math.floor(Math.random()*this.types.length)]},a.types=[{type:"ding",needs_notes:0},{type:"slam",needs_notes:0},{type:"left_slam",needs_notes:0},{type:"right_slam",needs_notes:0},{type:"ghost",needs_notes:0},{type:"punch",needs_notes:0},{type:"any_note",needs_notes:0},{type:"note",needs_notes:1},{type:"double",needs_notes:2},{type:"triple",needs_notes:3},{type:"staccato",needs_notes:1},{type:"brush_up",needs_notes:2},{type:"brush_down",needs_notes:2},{type:"harmonic",needs_notes:1}],a}(),App=function(){function t(t,e,n,a,s,i,r,o,p){this.handpan_tune=[{note:"C",alter:"#",octave:3,position:0},{note:"G",alter:"#",octave:3,position:1},{note:"A",alter:"",octave:4,position:2},{note:"B",alter:"",octave:4,position:3},{note:"C",alter:"#",octave:4,position:4},{note:"D",alter:"#",octave:4,position:5},{note:"E",alter:"",octave:4,position:6},{note:"F",alter:"#",octave:4,position:7},{note:"G",alter:"#",octave:4,position:8}],this.document=t,this.patterns_container=e,this.handpan_notes_input=n,this.handpan_notes_result_element=a,this.number_of_bars_input=s,this.number_of_bars_result_element=i,this.rhythm_inputs=o,this.regenerate_button=r,this.rhythm_input_to_enable=p}return t.prototype.run=function(){var e=this;this.regenerate_button.addEventListener("click",function(){return e.update()}),this.rhythm_input_to_enable.checked=!0,this.rhythm_inputs.forEach(function(t){return t.addEventListener("change",function(){return e.update()})}),this.number_of_bars_input.value="2",this.number_of_bars_input.addEventListener("input",function(){return e.update()}),this.update()},t.prototype.update=function(){var t=Number(this.number_of_bars_input.value),e=this.getRadioButtonValue(this.rhythm_inputs);this.number_of_bars_result_element.innerText=String(t),this.patterns_container.setAttribute("data-rhythm",e),this.patterns_container.innerHTML="";for(var n=!1,a=t*e,s=0;s<a;s++){var i=HandpanHit.getRandomHit(),r=this.createPatternItem(i);if(this.patterns_container.appendChild(r),r.classList.add(n?"hand-left":"hand-right"),r.classList.add(i.type),n=!n,s&&(s+1)%e==0&&s+1<a){var o=document.createElement("span");o.className="pattern_time_separator",this.patterns_container.appendChild(o)}}},t.prototype.createPatternItem=function(t){var e=document.createElement("div");e.className="pattern_item";var n=document.createElement("span");if(n.className="inner",n.innerText=t.type,e.appendChild(n),t.needs_notes){var a=document.createElement("div");a.className="notes";for(var s=[],i=0;i<t.needs_notes;i++){var r=this.handpan_tune[Math.floor(Math.random()*this.handpan_tune.length)],o=r.note+r.alter+r.octave;s.push(o)}a.innerHTML=s.join("<br>"),e.appendChild(a)}return e},t.prototype.getRadioButtonValue=function(t){for(var e=0,n=t;e<n.length;e++){var a=n[e];if(a.checked)return a.value}return null},t}();
1+
"use strict";
2+
var App = /** @class */ (function () {
3+
function App(document, patterns_container, handpan_notes_input, handpan_notes_result_element, number_of_bars_input, number_of_bars_result_element, regenerate_button, rhythm_inputs, rhythm_input_to_enable) {
4+
this.handpan_tune = [
5+
// <0 => low notes below the handpan
6+
// 0 => ding
7+
// 1 => lowest note on the top-part of the handpan
8+
{ "note": "C", "alter": "#", "octave": 3, "position": 0 },
9+
{ "note": "G", "alter": "#", "octave": 3, "position": 1 },
10+
{ "note": "A", "alter": "", "octave": 4, "position": 2 },
11+
{ "note": "B", "alter": "", "octave": 4, "position": 3 },
12+
{ "note": "C", "alter": "#", "octave": 4, "position": 4 },
13+
{ "note": "D", "alter": "#", "octave": 4, "position": 5 },
14+
{ "note": "E", "alter": "", "octave": 4, "position": 6 },
15+
{ "note": "F", "alter": "#", "octave": 4, "position": 7 },
16+
{ "note": "G", "alter": "#", "octave": 4, "position": 8 },
17+
];
18+
this._running = false;
19+
this.document = document;
20+
this.patterns_container = patterns_container;
21+
this.handpan_notes_input = handpan_notes_input;
22+
this.handpan_notes_result_element = handpan_notes_result_element;
23+
this.number_of_bars_input = number_of_bars_input;
24+
this.number_of_bars_result_element = number_of_bars_result_element;
25+
this.rhythm_inputs = rhythm_inputs;
26+
this.regenerate_button = regenerate_button;
27+
this.rhythm_input_to_enable = rhythm_input_to_enable;
28+
}
29+
App.prototype.run = function () {
30+
var _this = this;
31+
if (this._running) {
32+
throw 'Application is already running.';
33+
}
34+
this._running = true;
35+
this.regenerate_button.addEventListener('click', function () { return _this.update(); });
36+
// handpan_notes_result_element.value = 9;
37+
// handpan_notes_input.addEventListener('input', this.update);
38+
this.rhythm_input_to_enable.checked = true;
39+
this.rhythm_inputs.forEach(function (el) { return el.addEventListener('change', function () { return _this.update(); }); });
40+
this.number_of_bars_input.value = '2';
41+
this.number_of_bars_input.addEventListener('input', function () { return _this.update(); });
42+
this.update();
43+
};
44+
App.prototype.update = function () {
45+
// const handpan_notes = handpan_notes_input.value;
46+
var number_of_bars = Number(this.number_of_bars_input.value);
47+
var rhythm = this.getRadioButtonValue(this.rhythm_inputs);
48+
// handpan_notes_result_element.innerText = handpan_notes;
49+
this.number_of_bars_result_element.innerText = String(number_of_bars);
50+
this.patterns_container.setAttribute('data-rhythm', rhythm);
51+
this.patterns_container.innerHTML = '';
52+
var left_switch = false;
53+
var number_of_notes = number_of_bars * rhythm;
54+
for (var i = 0; i < number_of_notes; i++) {
55+
// Choose a "hit" type randomly in the list
56+
var handpan_hit = HitType.getRandomHitType();
57+
var pattern_item = this.createPatternItem(handpan_hit);
58+
this.patterns_container.appendChild(pattern_item);
59+
// Alternate left/right
60+
pattern_item.classList.add(left_switch ? 'hand-left' : 'hand-right');
61+
pattern_item.classList.add(handpan_hit.type);
62+
left_switch = !left_switch;
63+
// Add a separator to keep pattern a suite of 4 elements
64+
var needs_separator = i && (i + 1) % rhythm === 0 && (i + 1) < number_of_notes;
65+
if (needs_separator) {
66+
var pattern_item_separator = document.createElement('span');
67+
pattern_item_separator.className = 'pattern_time_separator';
68+
this.patterns_container.appendChild(pattern_item_separator);
69+
}
70+
}
71+
};
72+
App.prototype.createPatternItem = function (handpan_hit) {
73+
var pattern_item = document.createElement('div');
74+
pattern_item.className = 'pattern_item';
75+
// Display handpan hit type
76+
var text_element = document.createElement('span');
77+
text_element.className = 'inner';
78+
text_element.innerText = handpan_hit.type;
79+
pattern_item.appendChild(text_element);
80+
// Handle potential notes to display if necessary
81+
if (handpan_hit.needs_notes) {
82+
var notes_element = document.createElement('div');
83+
notes_element.className = 'notes';
84+
// Choose as many random note in the list so we can display them as a helper
85+
var notes = [];
86+
for (var i = 0; i < handpan_hit.needs_notes; i++) {
87+
// Pick a random note
88+
var note = this.handpan_tune[Math.floor(Math.random() * this.handpan_tune.length)];
89+
var item_to_push = note.note + note.alter + note.octave;
90+
notes.push(item_to_push);
91+
}
92+
notes_element.innerHTML = notes.join('<br>');
93+
pattern_item.appendChild(notes_element);
94+
}
95+
return pattern_item;
96+
};
97+
App.prototype.getRadioButtonValue = function (radios_list) {
98+
for (var _i = 0, radios_list_1 = radios_list; _i < radios_list_1.length; _i++) {
99+
var item = radios_list_1[_i];
100+
if (item.checked) {
101+
return item.value;
102+
}
103+
}
104+
return null;
105+
};
106+
return App;
107+
}());
108+
var Hand;
109+
(function (Hand) {
110+
Hand[Hand["left"] = 0] = "left";
111+
Hand[Hand["right"] = 1] = "right";
112+
})(Hand || (Hand = {}));
113+
var HandpanHit = /** @class */ (function () {
114+
function HandpanHit(type, hand, notes) {
115+
this.type = type;
116+
this.hand = hand;
117+
}
118+
HandpanHit.createRandomHitType = function () {
119+
var random_boolean = Math.floor(Math.random() * 2);
120+
var hand = random_boolean ? Hand.left : Hand.right;
121+
var hit_type = HitType.getRandomHitType();
122+
return new HandpanHit(hit_type, hand, []);
123+
};
124+
return HandpanHit;
125+
}());
126+
var HitType = /** @class */ (function () {
127+
function HitType(type, needs_notes) {
128+
if (!HitType.isValidHitType(type)) {
129+
throw 'Invalid hit type';
130+
}
131+
this._type = type;
132+
this._needs_notes = needs_notes;
133+
}
134+
Object.defineProperty(HitType.prototype, "type", {
135+
get: function () {
136+
return this._type;
137+
},
138+
enumerable: true,
139+
configurable: true
140+
});
141+
Object.defineProperty(HitType.prototype, "needs_notes", {
142+
get: function () {
143+
return this._needs_notes;
144+
},
145+
enumerable: true,
146+
configurable: true
147+
});
148+
HitType.getRandomHitType = function () {
149+
var random_type = this.types[Math.floor(Math.random() * this.types.length)];
150+
return new HitType(random_type.type, random_type.needs_notes);
151+
};
152+
;
153+
HitType.isValidHitType = function (type) {
154+
var hitType = this.types.filter(function (item) {
155+
return item.type === type;
156+
});
157+
return hitType.length > 0;
158+
};
159+
;
160+
HitType.types = [
161+
{ "type": 'ding', "needs_notes": 0 },
162+
{ "type": 'slam', "needs_notes": 0 },
163+
{ "type": 'left_slam', "needs_notes": 0 },
164+
{ "type": 'right_slam', "needs_notes": 0 },
165+
{ "type": 'ghost', "needs_notes": 0 },
166+
{ "type": 'punch', "needs_notes": 0 },
167+
{ "type": 'any_note', "needs_notes": 0 },
168+
{ "type": 'note', "needs_notes": 1 },
169+
{ "type": 'double', "needs_notes": 2 },
170+
{ "type": 'triple', "needs_notes": 3 },
171+
{ "type": 'staccato', "needs_notes": 1 },
172+
{ "type": 'brush_up', "needs_notes": 2 },
173+
{ "type": 'brush_down', "needs_notes": 2 },
174+
{ "type": 'harmonic', "needs_notes": 1 },
175+
];
176+
return HitType;
177+
}());

package.json

+20-20
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
{
2-
"name": "@pierstoval/handpan",
3-
"version": "0.1.0",
4-
"description": "A small helper for handpan players",
5-
"repository": {
6-
"type": "git",
7-
"url": "git+https://github.com/Pierstoval/handpan.git"
8-
},
9-
"scripts": {
10-
"build": "tsc index.ts --outDir build",
11-
"watch": "tsc index.ts --outDir build --watch"
12-
},
13-
"author": "Pierstoval",
14-
"license": "MIT",
15-
"bugs": {
16-
"url": "https://github.com/Pierstoval/handpan/issues"
17-
},
18-
"homepage": "https://github.com/Pierstoval/handpan",
19-
"dependencies": {
20-
"typescript": "^3.5.3"
21-
}
2+
"name": "@pierstoval/handpan",
3+
"version": "0.1.0",
4+
"description": "A small helper for handpan players",
5+
"repository": {
6+
"type": "git",
7+
"url": "git+https://github.com/Pierstoval/handpan.git"
8+
},
9+
"scripts": {
10+
"build": "tsc",
11+
"watch": "tsc --watch"
12+
},
13+
"author": "Pierstoval",
14+
"license": "MIT",
15+
"bugs": {
16+
"url": "https://github.com/Pierstoval/handpan/issues"
17+
},
18+
"homepage": "https://github.com/Pierstoval/handpan",
19+
"dependencies": {
20+
"typescript": "^3.5.3"
21+
}
2222
}

index.ts src/App.ts

+10-48
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,4 @@
11

2-
// Reminder of the common chromatic scale in C:
3-
// C -> C♯ -> D♭ -> D -> D♯ -> E♭ -> E -> E♯/F♭ -> F -> F♯ -> G♭ -> G -> G♯ -> A♭ -> A -> A♯ -> B♭ -> B -> B♯/C♭ -> C
4-
5-
// Note: the "position" attribute is not used for now, but will be in the future when people will customize their handpan
6-
7-
class HandpanHit {
8-
private static readonly types = [
9-
{"type": 'ding', "needs_notes": 0},
10-
{"type": 'slam', "needs_notes": 0},
11-
{"type": 'left_slam', "needs_notes": 0},
12-
{"type": 'right_slam', "needs_notes": 0},
13-
{"type": 'ghost', "needs_notes": 0},
14-
{"type": 'punch', "needs_notes": 0},
15-
{"type": 'any_note', "needs_notes": 0},
16-
{"type": 'note', "needs_notes": 1},
17-
{"type": 'double', "needs_notes": 2}, // "power" chord
18-
{"type": 'triple', "needs_notes": 3}, // chord
19-
{"type": 'staccato', "needs_notes": 1}, // A note that you just "mute" with the side of the other hand
20-
{"type": 'brush_up', "needs_notes": 2}, // 2 Notes you chain really fast in the specified duration
21-
{"type": 'brush_down', "needs_notes": 2}, // 2 Notes you chain really fast in the specified duration
22-
{"type": 'harmonic', "needs_notes": 1},
23-
];
24-
25-
private readonly type: string;
26-
27-
constructor(type: string, hand, notes) {
28-
if (!HandpanHit.isValidHitType(type)) {
29-
throw 'Invalid hit type';
30-
}
31-
32-
this.type = type;
33-
}
34-
35-
private static isValidHitType(type: string) {
36-
let hitType = this.types.filter(function(item) {
37-
return item.type === type;
38-
});
39-
40-
return hitType.length > 0;
41-
};
42-
43-
public static getRandomHit() {
44-
return this.types[Math.floor(Math.random() * this.types.length)];
45-
};
46-
}
47-
482
class App {
493
private readonly document: HTMLDocument;
504
private readonly patterns_container: HTMLElement;
@@ -56,7 +10,7 @@ class App {
5610
private readonly regenerate_button: HTMLElement;
5711
private readonly rhythm_input_to_enable: HTMLInputElement;
5812

59-
handpan_tune = [
13+
private readonly handpan_tune = [
6014
// <0 => low notes below the handpan
6115
// 0 => ding
6216
// 1 => lowest note on the top-part of the handpan
@@ -71,6 +25,8 @@ class App {
7125
{"note": "G", "alter": "#", "octave": 4, "position": 8},
7226
];
7327

28+
private _running: boolean = false;
29+
7430
constructor(
7531
document: HTMLDocument,
7632
patterns_container: HTMLElement,
@@ -94,6 +50,12 @@ class App {
9450
}
9551

9652
run() {
53+
if (this._running) {
54+
throw 'Application is already running.';
55+
}
56+
57+
this._running = true;
58+
9759
this.regenerate_button.addEventListener('click', () => this.update());
9860

9961
// handpan_notes_result_element.value = 9;
@@ -125,7 +87,7 @@ class App {
12587

12688
for (let i = 0; i < number_of_notes; i++) {
12789
// Choose a "hit" type randomly in the list
128-
const handpan_hit = HandpanHit.getRandomHit();
90+
const handpan_hit = HitType.getRandomHitType();
12991

13092
let pattern_item = this.createPatternItem(handpan_hit);
13193

src/Hand.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
enum Hand {
3+
left,
4+
right,
5+
}

src/HandpanHit.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
class HandpanHit {
3+
private readonly type: HitType;
4+
private readonly hand: Hand;
5+
6+
private constructor(type: HitType, hand: Hand, notes) {
7+
this.type = type;
8+
this.hand = hand;
9+
}
10+
11+
public static createRandomHitType(): HandpanHit {
12+
let random_boolean = Math.floor(Math.random() * 2);
13+
let hand = random_boolean ? Hand.left : Hand.right;
14+
let hit_type = HitType.getRandomHitType();
15+
16+
return new HandpanHit(hit_type, hand, []);
17+
}
18+
}

src/HitType.ts

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
2+
class HitType {
3+
private static readonly types = [
4+
{"type": 'ding', "needs_notes": 0},
5+
{"type": 'slam', "needs_notes": 0},
6+
{"type": 'left_slam', "needs_notes": 0},
7+
{"type": 'right_slam', "needs_notes": 0},
8+
{"type": 'ghost', "needs_notes": 0},
9+
{"type": 'punch', "needs_notes": 0},
10+
{"type": 'any_note', "needs_notes": 0},
11+
{"type": 'note', "needs_notes": 1},
12+
{"type": 'double', "needs_notes": 2}, // "power" chord
13+
{"type": 'triple', "needs_notes": 3}, // chord
14+
{"type": 'staccato', "needs_notes": 1}, // A note that you just "mute" with the side of the other hand
15+
{"type": 'brush_up', "needs_notes": 2}, // 2 Notes you chain really fast in the specified duration
16+
{"type": 'brush_down', "needs_notes": 2}, // 2 Notes you chain really fast in the specified duration
17+
{"type": 'harmonic', "needs_notes": 1},
18+
];
19+
20+
private readonly _type: string;
21+
private readonly _needs_notes: number;
22+
23+
get type(): string {
24+
return this._type;
25+
}
26+
27+
get needs_notes(): number {
28+
return this._needs_notes;
29+
}
30+
31+
private constructor(type: string, needs_notes: number) {
32+
if (!HitType.isValidHitType(type)) {
33+
throw 'Invalid hit type';
34+
}
35+
36+
this._type = type;
37+
this._needs_notes = needs_notes;
38+
}
39+
40+
public static getRandomHitType(): HitType {
41+
let random_type = this.types[Math.floor(Math.random() * this.types.length)];
42+
43+
return new HitType(random_type.type, random_type.needs_notes);
44+
};
45+
46+
private static isValidHitType(type: string): boolean {
47+
let hitType = this.types.filter(function(item) {
48+
return item.type === type;
49+
});
50+
51+
return hitType.length > 0;
52+
};
53+
}

0 commit comments

Comments
 (0)