-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
A well-organized system #3
base: main
Are you sure you want to change the base?
Changes from all commits
ac73915
35ecab1
7b05dca
7a90da3
196a968
1f6deb4
9171960
b977ca0
f2b39a6
e1858fc
2589bab
f85c7d3
5699855
3c152de
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,180 +1,15 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
|
||
<head> | ||
<meta charset="UTF-8"> | ||
<meta charset="UTF-8"> | ||
<title>Pomodoro</title> | ||
</head> | ||
<body> | ||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/p5.js"></script> | ||
<script src="p5.sound.js"></script> | ||
<script> | ||
var pomodoromode=false; | ||
var modes=["60x60","25x25","45x10","1x1","0.1x1","90x90"];//add modes here | ||
var buttons=[]; | ||
var work,rest; | ||
var working=true;//false=resting | ||
var currentButtonsAmount=0; | ||
var buttonWidth,buttonHeight;//global | ||
var startTime; | ||
var endTime; | ||
var doOnce=false;//for pomodoro screen | ||
var doOnce2=false;//for start screen | ||
var theText;//for pomodoro screen - global | ||
var timeMode=1;//0=1hours,60minutes,3600seconds / 1=1hours,0minutes,0seconds | ||
var timeLeft; | ||
var bg;//global bg color | ||
var _reset=false; | ||
var soundEffect; | ||
function setup() { | ||
buttonWidth=windowWidth/5; | ||
buttonHeight=windowHeight/10; | ||
|
||
createCanvas(windowWidth, windowHeight); | ||
|
||
soundEffect = loadSound('sound effect.mp3'); | ||
|
||
{//setup screen | ||
background(200); | ||
|
||
textAlign(CENTER); | ||
|
||
var buttonsAmount=modes.length; | ||
//create starting buttons | ||
for(var i=0;i<buttonsAmount;i++){ | ||
buttons[i] = createButton(modes[i]); | ||
buttons[i].position(windowWidth/2-buttonWidth/2, (windowHeight/2)+(i*buttonHeight)-(buttonsAmount*buttonHeight/2)); | ||
buttons[i].size(buttonWidth,buttonHeight); | ||
buttons[i].mousePressed((function(index){ | ||
return function(){ | ||
setMode(modes[index]); | ||
} | ||
})(i));//IIFE | ||
} | ||
} | ||
} | ||
function draw() { | ||
if(_reset){//executes once to reset program | ||
//console.log("asldkas"); | ||
buttons.forEach((b)=>{b.remove()}); | ||
pomodoromode=false; | ||
timeMode=1; | ||
clear(); | ||
{//setup screen | ||
background(200); | ||
|
||
textAlign(CENTER); | ||
|
||
var buttonsAmount=modes.length; | ||
//create starting buttons | ||
for(var i=0;i<buttonsAmount;i++){ | ||
buttons[i] = createButton(modes[i]); | ||
buttons[i].position(windowWidth/2-buttonWidth/2, (windowHeight/2)+(i*buttonHeight)-(buttonsAmount*buttonHeight/2)); | ||
buttons[i].size(buttonWidth,buttonHeight); | ||
buttons[i].mousePressed((function(index){ | ||
return function(){ | ||
setMode(modes[index]); | ||
} | ||
})(i));//IIFE | ||
} | ||
} | ||
|
||
_reset=false; | ||
} | ||
if(bg=="grey"){ | ||
background(color(30)); | ||
} | ||
if(pomodoromode){ | ||
pomodoro(work,rest); | ||
}else{ | ||
|
||
} | ||
|
||
} | ||
function mouseClicked(){ | ||
if(pomodoromode){ | ||
timeMode=!timeMode; | ||
} | ||
} | ||
function setMode(_mode){ | ||
m=1; | ||
work=_mode.substring(0,_mode.indexOf("x")); | ||
rest=_mode.substring(_mode.indexOf("x") + 1); | ||
//console.log(work+"+"+rest); | ||
|
||
buttons.forEach((b)=>{b.remove()}); | ||
|
||
currentButtonsAmount=1; | ||
buttons[0]=makeButton("start",1,()=>{doOnce=true;pomodoromode=true}); | ||
} | ||
function pomodoro(_work,_rest){//int,int | ||
textSize((windowWidth+windowHeight)/2/25); | ||
|
||
if(doOnce){ | ||
buttons.forEach((b)=>{b.remove()}); | ||
startTime=getTime(); | ||
endTime=getTargetTime((working==true)?_work:_rest); | ||
currentButtonsAmount=6; | ||
buttons[0]=makeButton("Reset",6,()=>{_reset=true;}); | ||
|
||
soundEffect.play(); | ||
|
||
doOnce=false; | ||
} | ||
background((working==true)?color(0,255,0):color(0,0,255)); | ||
|
||
timeLeft=getTimeDifference(millis()/1000,endTime); | ||
if(timeLeft[2]<=0){//negative seconds left | ||
working=!working;//switch modes | ||
doOnce=true;//recalculate time to finish | ||
} | ||
if(timeMode==0){//set text based on display mode | ||
theText=text(((working==true)?"Working":"Resting")+" for "+((working==true)?_work:_rest)+" minutes. \n" | ||
+timeLeft[0]+" hours remaining. \n" | ||
+timeLeft[1]+" minutes remaining. \n" | ||
+timeLeft[2]+" seconds remaining. \n" | ||
,windowWidth/2,windowHeight/2); | ||
}else{//=1 | ||
var secondsfixed=(timeLeft[2]>=60)?timeLeft[2]%60:timeLeft[2]; | ||
secondsfixed=parseFloat(secondsfixed).toFixed(2); | ||
theText=text(((working==true)?"Working":"Resting")+" for "+((working==true)?_work:_rest)+" minutes. \n" | ||
+timeLeft[0]+" hours and\n" | ||
+((timeLeft[1]>=60)?timeLeft[1]%60:timeLeft[1])+" minutes and\n" | ||
+secondsfixed+" seconds remaining. \n" | ||
,windowWidth/2,windowHeight/2); | ||
} | ||
|
||
} | ||
function makeButton(txt,totalButtons,mPressed){//string,int,function | ||
//totalButtons=intended total number of buttons | ||
//currentButtonsAmount=the current number of buttons on screen before creation of this one | ||
var tmp; | ||
tmp = createButton(txt); | ||
tmp.position(windowWidth/2-buttonWidth/2, (windowHeight/2)+(currentButtonsAmount*buttonHeight)-(totalButtons*buttonHeight/2)); | ||
tmp.size(buttonWidth,buttonHeight); | ||
tmp.mousePressed(mPressed);//function | ||
|
||
currentButtonsAmount++; | ||
return tmp; | ||
} | ||
function getTime(){//get time in seconds since start of program | ||
return millis()/1000; | ||
} | ||
function getTargetTime(mins){//mins=minutes in the future | ||
return millis()/1000+(mins*60);//returns time in seconds from setup() to target time | ||
} | ||
function getTimeDifference(current,target){//params are seconds | ||
var temp=[];//0=hours,1=minutes,2=seconds | ||
var diff=(target-current)//difference in seconds | ||
temp[0] = Math.floor(diff/60/60);//hours | ||
temp[1] = Math.floor(diff/60);//minutes | ||
temp[2] = diff;//seconds | ||
temp[2] = temp[2].toFixed(2);//seconds to two decimal places | ||
|
||
return temp; | ||
} | ||
function windowResized() { | ||
resizeCanvas(windowWidth, windowHeight); | ||
} | ||
|
||
</script> | ||
<body> | ||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/p5.js"></script> | ||
<script src="static/js/p5.sound.js"></script> | ||
<script type="module" src="static/js/main.js"></script> | ||
</body> | ||
</html> | ||
|
||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
// Due to the way processing works, some variables that are treated as constants can't be declared as such, because they must be set in `setup()`. | ||
// We could probably avert this issue by severing the processing library from this project, and rewriting it in terms of DOM interaction. | ||
|
||
import { timeFormatter } from "./presets.js"; | ||
import { getTargetTime, getTime, getTimeDifference } from "./timeUtils.js"; | ||
import TimeInformation from "./timeInformation.js"; | ||
|
||
const modes = ["60x60", "25x25", "45x10", "1x1", "0.1x1", "0.02x0.02", "90x90"]; //add modes here | ||
|
||
var timerRunning = false; | ||
var buttons = []; | ||
var currentWorkTime, currentRestTime; | ||
var working = true; //false=resting | ||
var currentButtonsAmount = 0; | ||
var buttonWidth, buttonHeight; // Should be constant, but due to the way processing works, must be set in `setup()`. | ||
var endTime; | ||
var resetTimer = false; //for pomodoro screen | ||
var theText; //for pomodoro screen - global | ||
var timeLeft; | ||
var soundEffect; // Should be constant. | ||
Comment on lines
+10
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All of these should be able to be turned into |
||
|
||
function setup() { | ||
buttonWidth = windowWidth / 5; | ||
buttonHeight = windowHeight / 10; | ||
|
||
createCanvas(windowWidth, windowHeight); | ||
|
||
soundEffect = loadSound("static/audio/sound effect.mp3"); | ||
|
||
background(200); | ||
textAlign(CENTER); | ||
buttons = makeButtonsFromModes(modes); | ||
} | ||
|
||
function draw() { | ||
if (timerRunning) pomodoro(currentWorkTime, currentRestTime); | ||
} | ||
|
||
function resetProgram() { | ||
//executes once to reset program | ||
buttons.forEach((b) => b.remove()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do see this call repeated in a few places. It's probably wise to extract this into its own function. |
||
timerRunning = false; | ||
clear(); | ||
//setup screen | ||
background(200); | ||
|
||
textAlign(CENTER); | ||
|
||
buttons = makeButtonsFromModes(modes); | ||
} | ||
|
||
function mouseClicked() { | ||
if (timerRunning) timeFormatter.next(); | ||
} | ||
|
||
/** | ||
* Makes one button to start the timer with the specified mode and destroys all other buttons. | ||
* @param {string} mode - The timer mode, formatted like so: `"<Work time>x<Rest time>"` | ||
*/ | ||
function setMode(mode) { | ||
currentWorkTime = mode.substring(0, mode.indexOf("x")); | ||
currentRestTime = mode.substring(mode.indexOf("x") + 1); | ||
|
||
buttons.forEach((b) => b.remove()); | ||
|
||
buttons = [ | ||
makeButton( | ||
"start", | ||
(currentButtonsAmount = 1), | ||
() => (resetTimer = timerRunning = true) | ||
), | ||
]; | ||
} | ||
|
||
/** | ||
* Updates the screen to show the proper text about time left in a session. | ||
* @param {number} workTime - The time to spend working | ||
* @param {number} restTime - The time to spend resting | ||
*/ | ||
function pomodoro(workTime, restTime) { | ||
textSize((windowWidth + windowHeight) / 2 / 25); | ||
|
||
if (resetTimer) { | ||
buttons.forEach((b) => b.remove()); | ||
endTime = getTargetTime(working ? workTime : restTime); | ||
buttons = [ | ||
makeButton( | ||
"Reset", | ||
(currentButtonsAmount = modes.length), | ||
resetProgram | ||
), | ||
]; | ||
|
||
soundEffect.play(); | ||
|
||
resetTimer = false; | ||
} | ||
Comment on lines
+83
to
+97
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could be better, we should strive for separation of concerns. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be ideal to make a function call instead of setting a global variable used in another function, maybe making a |
||
|
||
background(working ? color(0, 255, 0) : color(64, 64, 255)); | ||
|
||
timeLeft = getTimeDifference(getTime(), endTime); | ||
|
||
if (timeLeft.seconds <= 0) { | ||
working = !working; | ||
resetTimer = true; //recalculate time to finish | ||
} | ||
|
||
const currentTimeInfo = new TimeInformation( | ||
working, | ||
workTime, | ||
restTime, | ||
timeLeft | ||
); | ||
|
||
theText = standardText(timeFormatter.textFrom(currentTimeInfo)); | ||
Comment on lines
+108
to
+115
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This section of code now adheres to the Open-Closed Principle. |
||
} | ||
|
||
function standardText(txt) { | ||
return text(txt, windowWidth / 2, windowHeight / 2); | ||
} | ||
|
||
/** | ||
* Creates a list of buttons from a list of timer modes. Each button will start the corresponding mode when clicked. | ||
* @param {string[]} modes - List of timer modes that the buttons should start. | ||
* @returns {Button[]} The list of buttons that start the timer with their mode. | ||
*/ | ||
function makeButtonsFromModes(modes) { | ||
return modes | ||
.map(createButton) | ||
.map((b, idx) => | ||
b.position( | ||
windowWidth / 2 - buttonWidth / 2, | ||
windowHeight / 2 + | ||
idx * buttonHeight - | ||
(modes.length * buttonHeight) / 2 | ||
Comment on lines
+132
to
+135
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is complex logic that would be good to describe in more detail. |
||
) | ||
) | ||
.map((b) => b.size(buttonWidth, buttonHeight)) | ||
.map((b, idx) => b.mousePressed(() => setMode(modes[idx]))); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This may not be the best solution, but at least we depend only on a parameter. |
||
} | ||
|
||
/** | ||
* Creates a button on the screen. | ||
* @param {string} txt - The text on the button | ||
* @param {number} totalButtons - The intended total number of buttons | ||
* @param {() => void} mPressed - The callback to be ran when the button is clicked | ||
* @returns | ||
*/ | ||
function makeButton(txt, totalButtons, mPressed) { | ||
//currentButtonsAmount=the current number of buttons on screen before creation of this one | ||
var button = createButton(txt); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could be |
||
button.position( | ||
windowWidth / 2 - buttonWidth / 2, | ||
windowHeight / 2 + | ||
currentButtonsAmount * buttonHeight - | ||
(totalButtons * buttonHeight) / 2 | ||
); | ||
Comment on lines
+152
to
+157
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This logic looks to be duplicated in |
||
button.size(buttonWidth, buttonHeight); | ||
button.mousePressed(mPressed); | ||
|
||
currentButtonsAmount++; | ||
|
||
return button; | ||
} | ||
|
||
window.setup = setup; | ||
window.mouseClicked = mouseClicked; | ||
window.draw = draw; | ||
Comment on lines
+166
to
+168
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Small trick for |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import TimeFormatter from "./timeFormatter.js"; | ||
import * as timeModes from "./timeModes.js"; | ||
|
||
export const timeFormatter = new TimeFormatter([ | ||
timeModes.dependent, | ||
timeModes.independent, | ||
]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Separation of concerns - I called this one "Code-Interface Segregation".