diff --git a/qml/CategoryPage.qml b/qml/CategoryPage.qml index 23e9871..c634a88 100644 --- a/qml/CategoryPage.qml +++ b/qml/CategoryPage.qml @@ -58,8 +58,36 @@ Rectangle { function updateSystemDesignModel() { categoryModel.clear(); - categoryModel.append({ name: "Load balancer", selected: false, enabled: true, type: "System Design" }); - categoryModel.append({ name: "Cache", selected: false, enabled: true, type: "System Design" }); + categoryModel.append({ name: "Load balancer", selected: false, enabled: true, type: "System Design" }); + categoryModel.append({ name: "Binary Search", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Bit Manipulation", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Combinatorics", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Div. Conq.", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Disjoint Set", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "DP", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Game Theory", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Geometry", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Cache", selected: false, enabled: true, type: "System Design" }); + categoryModel.append({ name: "Greedy", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Heap", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Intervals", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Linked List", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Mathematics", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Pigeonhole", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Recursion", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Searching", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Segment Tree", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Sliding Window", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Sorting", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "String", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Topo. Sort", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Tree", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Trie", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Two Pointers", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Union-Find", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Matrix", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Database", selected: false, enabled: false, type: "System Design" }); + categoryModel.append({ name: "Shell", selected: false, enabled: false, type: "System Design" }); } function updateSelectedCategories() { diff --git a/qml/StatsPage.qml b/qml/StatsPage.qml index f196c9c..6046a5d 100644 --- a/qml/StatsPage.qml +++ b/qml/StatsPage.qml @@ -11,7 +11,9 @@ Rectangle { property string lastUpdateTime: "" property var questionColorMap: {} property bool detailsButtonCheckedState: false + property bool previousWeekCheckedState: false property bool dataReady: false + property var today: null Layout.fillWidth: true Layout.fillHeight: true @@ -25,18 +27,21 @@ Rectangle { onTriggered: { if (speedCanvas.visible) { - d.populateGraphSpentTimeData(); + statsPage.today = d.parseDate(d.getCurrentDate()) + d.populateGraphSpentTimeData(statsPage.today); } else if (successCanvas.visible) { d.populateGraphGaussianData(); } else { - d.populateGraphDetailedSpentTimeData(); + d.populateGraphDetailedSpentTimeData(statsPage.today); } } } Component.onCompleted: { d.populateGraphGaussianData(); - d.populateGraphSpentTimeData(); + + statsPage.today = d.parseDate(d.getCurrentDate()) + d.populateGraphSpentTimeData(statsPage.today); sessionObject.loadSession(); statsPage.fluctuation = d.getFluctuation(); @@ -57,6 +62,36 @@ Rectangle { QtObject { id: d + function calculateCurrentWeekStart(today) { + const { startOfWeek } = d.getCurrentWeekRange(today); + const currentWeekStartDate = new Date(startOfWeek); + + if (isNaN(currentWeekStartDate)) { + console.error("Invalid startOfWeek date:", startOfWeek); + return null; + } + + currentWeekStartDate.setDate(currentWeekStartDate.getDate()); + const currentWeekStart = currentWeekStartDate.toISOString().split("T")[0]; + + return currentWeekStart; + } + + function calculatePreviousWeekStart(today) { + const { startOfWeek } = d.getCurrentWeekRange(today); + const currentWeekStartDate = new Date(startOfWeek); + + if (isNaN(currentWeekStartDate)) { + console.error("Invalid startOfWeek date:", startOfWeek); + return null; + } + + currentWeekStartDate.setDate(currentWeekStartDate.getDate() - 7); + const previousWeekStart = currentWeekStartDate.toISOString().split("T")[0]; + + return previousWeekStart; + } + function getBarColor(barHeight, yAxisMax) { let baseRed = 0.4; // Slightly muted red let baseGreen = 0.5; // Slightly muted green @@ -137,7 +172,14 @@ Rectangle { return new Date(year, month - 1, day); } - function getCurrentWeekRange(today) { + function getCurrentWeekRange(todayString) { + const today = new Date(todayString); + + if (isNaN(today)) { + console.error("Invalid date:", todayString); + return null; + } + const dayOfWeek = today.getDay(); const startOfWeek = new Date(today); const endOfWeek = new Date(today); @@ -148,7 +190,7 @@ Rectangle { return { startOfWeek, endOfWeek }; } - function populateGraphSpentTimeData() { + function populateGraphSpentTimeData(today) { graphData.clear(); var daySpentTimes = { @@ -161,7 +203,6 @@ Rectangle { "Sunday": { total: 0, count: 0 }, }; - const today = d.parseDate(d.getCurrentDate()); const { startOfWeek, endOfWeek } = d.getCurrentWeekRange(today); for (var question in sessionObject.successfulImplementations) { @@ -197,7 +238,7 @@ Rectangle { statsPage.lastUpdateTime = d.getCurrentTime(); } - function populateGraphDetailedSpentTimeData() { + function populateGraphDetailedSpentTimeData(today) { graphData.clear(); const daySpentTimes = { @@ -210,7 +251,6 @@ Rectangle { "Sunday": [] }; - const today = d.parseDate(d.getCurrentDate()); const { startOfWeek, endOfWeek } = d.getCurrentWeekRange(today); for (const question in sessionObject.successfulImplementations) { @@ -298,7 +338,7 @@ Rectangle { function formatTime(seconds) { const minutes = String(Math.floor(seconds / 60)).padStart(2, '0'); - const remainingSeconds = String((seconds % 60)).padStart(2, '0'); + const remainingSeconds = String((seconds % 60).toFixed(2, 0)).padStart(2, '0'); return `${minutes}m${remainingSeconds}`; } @@ -436,7 +476,8 @@ Rectangle { enabled: !detailsButtonCheckedState onToggled: { - speedCanvas.visible ? d.populateGraphSpentTimeData() : d.populateGraphGaussianData() + statsPage.today = d.parseDate(d.getCurrentDate()) + speedCanvas.visible ? d.populateGraphSpentTimeData(statsPage.today) : d.populateGraphGaussianData() } } @@ -673,7 +714,7 @@ Rectangle { ctx.save(); ctx.translate(xPos, yPos); var textWidth = d.formatTime(point.time).length - ctx.fillText(point.time.toFixed(2, 0).padStart(2, '0'), 0, 0) + ctx.fillText(d.formatTime(point.time.toFixed(2, 0)).padStart(2, '0'), 0, 0) ctx.restore(); } @@ -922,10 +963,19 @@ Rectangle { onClicked: { detailsButtonCheckedState = !detailsButtonCheckedState + var today = null + + if (!previousWeekCheckedState) { + today = d.parseDate(d.getCurrentDate()) + } else { + let currentDay = d.parseDate(d.getCurrentDate()) + today = d.calculatePreviousWeekStart(currentDay) + } + if (detailsButtonCheckedState) { - d.populateGraphDetailedSpentTimeData() + d.populateGraphDetailedSpentTimeData(today) } else { - d.populateGraphSpentTimeData() + d.populateGraphSpentTimeData(today) } } Layout.alignment: Qt.AlignHCenter @@ -952,6 +1002,54 @@ Rectangle { } } } + + Button { + id: previousWeek + enabled: !control.checked + text: qsTr("Previous week") + onClicked: { + previousWeekCheckedState = !previousWeekCheckedState + + var today = null + + if (!previousWeekCheckedState) { + today = d.parseDate(d.getCurrentDate()) + } else { + let currentDay = d.parseDate(d.getCurrentDate()) + today = d.calculatePreviousWeekStart(currentDay) + } + + if (detailsButtonCheckedState) { + d.populateGraphDetailedSpentTimeData(today) + } else { + d.populateGraphSpentTimeData(today) + } + } + + Layout.alignment: Qt.AlignHCenter + width: 100 + height: 30 + font.bold: sessionObject.isFontBold + + contentItem: Text { + text: previousWeek.text + font: previousWeek.font + opacity: enabled ? 1.0 : 0.3 + color: previousWeekCheckedState ? "#F7F7F7" : themeObject.textColor + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + elide: Text.ElideRight + } + + background: Rectangle { + radius: 10 + border.width: 1 + border.color: themeObject.buttonBorderColor + color: { + return !previousWeekCheckedState ? themeObject.buttonColor : themeObject.buttonActionColor + } + } + } } } }