xxxxxxxxxx
286
let heading;
let phaseDropdown, dayInput, generateButton;
let diaryEntry = "";
let currentPhase = "Follicular";
let currentDay = 1;
let errorMsg = "";
let isGenerated = false; // Tracks if a valid diary has been generated yet
// Arrays for diary entry options:
let follicularEntries = [
"A sense of renewal washes over me. The world feels lighter, possibilities endless.",
"Today, I feel an electric creativity coursing through my veins.",
"My mind buzzes with fresh ideas, and my spirit feels bright."
];
let ovulationEntries = [
"I catch my reflection and smile—there’s a glow, an energy I can’t explain.",
"Today, I feel particularly confident, like the world is mine for the taking.",
"My social side is shining; I want to connect, flirt, and celebrate life."
];
let lutealEntries = [
"The air feels heavy. My body craves warmth, my mind whispers doubts.",
"I feel introspective and a bit anxious; maybe a quiet evening will help me refocus.",
"My cravings are strong today—comfort food and a cozy blanket, please."
];
let menstrualEntries = [
"My body is in self-care mode. I’m slowing down to listen to what I need.",
"Tiredness settles in, but there’s a calm acceptance in this ritual.",
"I’m reflective today. Letting go of the old, making space for the new."
];
let motivationalPhrases = [
"But I know I can get through it. One gentle step at a time.",
"Today, I choose kindness for myself.",
"I remind myself that every phase passes, and brighter days lie ahead."
];
// Animation variables
let floatingObjects = [];
let bgColor;
function setup() {
createCanvas(600, 400);
// Heading in Merriweather
heading = createElement('h1', 'Emotional Diary of the Cycle');
heading.style('font-family', 'Merriweather, serif');
heading.style('color', '#DA4E60');
heading.position(100, 0);
// Dropdown for phases with day ranges
phaseDropdown = createSelect();
phaseDropdown.option("Follicular (Days 1-14)", "Follicular");
phaseDropdown.option("Ovulation (Days 14-16)", "Ovulation");
phaseDropdown.option("Luteal (Days 17-28)", "Luteal");
phaseDropdown.option("Menstrual (Days 1-5)", "Menstrual");
phaseDropdown.changed(() => {
currentPhase = phaseDropdown.value();
});
// Style the dropdown
phaseDropdown.position(65, 76);
phaseDropdown.style('padding', '5px');
phaseDropdown.style('border', '2px solid #DA4E60');
phaseDropdown.style('border-radius', '5px');
phaseDropdown.style('font-family', 'Merriweather, serif');
// Input for day
dayInput = createInput("1");
dayInput.attribute("type", "number");
// We no longer parse the day on "changed" here,
// so that the user doesn't have to press Enter or lose focus
dayInput.position(220, 72);
dayInput.style('padding', '5px');
dayInput.style('border', '2px solid #DA4E60');
dayInput.style('border-radius', '5px');
dayInput.style('font-family', 'Merriweather, serif');
// Button to generate diary entry
generateButton = createButton("Generate Diary Entry");
generateButton.mousePressed(generateDiaryEntry);
generateButton.position(400, 70);
generateButton.style('padding', '8px 10px');
generateButton.style('border', 'none');
generateButton.style('border-radius', '5px');
generateButton.style('background-color', '#DA4E60');
generateButton.style('color', '#fff');
generateButton.style('font-family', 'Merriweather, serif');
generateButton.style('cursor', 'pointer');
// Initialize floating objects for animation
for (let i = 0; i < 50; i++) {
floatingObjects.push(new FloatingObject());
}
// Default background color
bgColor = color(240, 240, 255);
textAlign(CENTER, CENTER);
}
function draw() {
pickBackgroundColor();
background(bgColor);
// Update and display the floating objects
for (let obj of floatingObjects) {
obj.update();
obj.display(currentPhase);
}
// Display error message if any
fill(0);
textSize(14);
text(errorMsg, width/2, height/2 - 80, width * 0.8);
// Draw a semi-transparent rectangle lower on the canvas
fill(255, 230);
noStroke();
rectMode(CENTER);
rect(width/2, height/2 + 30, width * 0.7, height * 0.4, 20);
// If a valid diary has been generated, show day/phase and diary text
// Otherwise, show "Hello"
textFont('Comic Sans MS');
textSize(18);
fill('#DA4E60');
if (isGenerated) {
text(`You are in Day ${currentDay} of the ${currentPhase} Phase!`, width/2, height/2 + 10, width * 0.6);
// Poetic diary entry in italics
textSize(16);
textStyle(ITALIC);
fill(0);
text(`"${diaryEntry}"`, width/2, height/2 + 50, width * 0.6);
} else {
textSize(20);
textStyle(NORMAL);
fill(0);
text("Hello", width/2, height/2 + 30);
}
}
/**
* Generates a diary entry based on the current phase and day
*/
function generateDiaryEntry() {
// Always parse the latest day input on button click
currentDay = parseInt(dayInput.value(), 10);
if (isNaN(currentDay)) {
currentDay = 0;
}
// Clear previous error message
errorMsg = "";
// Validate day range
let isValid = validateDayRange(currentPhase, currentDay);
if (!isValid) {
errorMsg = "Please recheck your phase/day value. The day entered is outside the range for this phase.";
diaryEntry = "";
isGenerated = false; // stay in "Hello" mode
return;
}
// If valid, we proceed
let entry = "";
switch (currentPhase) {
case "Follicular":
entry = random(follicularEntries);
break;
case "Ovulation":
entry = random(ovulationEntries);
break;
case "Luteal":
entry = random(lutealEntries);
// Possibly append a motivational phrase
entry += " " + random(motivationalPhrases);
break;
case "Menstrual":
entry = random(menstrualEntries);
// Possibly append a motivational phrase
entry += " " + random(motivationalPhrases);
break;
}
diaryEntry = entry;
isGenerated = true; // a valid entry was generated
}
/**
* Validate if the day is correct for the selected phase
*/
function validateDayRange(phase, day) {
// Keeping your day-limit logic the same
if (phase === "Follicular") {
// Days 1-13
return day >= 1 && day <= 13;
} else if (phase === "Ovulation") {
// Days 14-16
return day >= 14 && day <= 16;
} else if (phase === "Luteal") {
// Days 17-28
return day >= 17 && day <= 28;
} else if (phase === "Menstrual") {
// Days 1-5
return day >= 1 && day <= 5;
}
return false;
}
/**
* Adjust background color based on phase
*/
function pickBackgroundColor() {
if (currentPhase === "Follicular") {
bgColor = color(200, 255, 200); // soft green
} else if (currentPhase === "Ovulation") {
bgColor = color(255, 220, 200); // warm peach
} else if (currentPhase === "Luteal") {
bgColor = color(200, 200, 255); // soft blue/purple
} else if (currentPhase === "Menstrual") {
bgColor = color(255, 200, 200); // soft red/pink
}
}
/**
* FloatingObject class for background animation
*/
class FloatingObject {
constructor() {
this.x = random(width);
this.y = random(height);
this.size = random(5, 15);
this.speed = random(0.5, 2);
this.angle = random(TWO_PI);
}
update() {
// Move upwards slightly, sway side to side
this.y -= this.speed * 0.2;
this.x += sin(this.angle) * 0.2;
this.angle += 0.01;
// Wrap around top
if (this.y < 0) {
this.y = height;
this.x = random(width);
}
}
display(phase) {
noStroke();
let shapeColor;
switch (phase) {
case "Follicular":
shapeColor = color(random(50, 100), random(200, 255), random(50, 100));
fill(shapeColor);
ellipse(this.x, this.y, this.size, this.size);
break;
case "Ovulation":
shapeColor = color(random(255), random(100, 150), random(100, 150));
fill(shapeColor);
rectMode(CENTER);
push();
translate(this.x, this.y);
rotate(this.angle);
rect(0, 0, this.size, this.size);
pop();
break;
case "Luteal":
shapeColor = color(random(100, 150));
fill(shapeColor);
ellipse(this.x, this.y, this.size, this.size);
break;
case "Menstrual":
shapeColor = color(random(150, 255), 0, 0, random(100, 255));
fill(shapeColor);
ellipse(this.x, this.y, this.size, this.size);
break;
}
}
}