bump node version in deployment
continuous-integration/drone/push Build is failing Details

This commit is contained in:
hyper-neutrino 2024-04-03 10:54:21 -04:00
commit 7b9f798270
121 changed files with 18206 additions and 0 deletions

46
.drone.yml Normal file
View File

@ -0,0 +1,46 @@
---
kind: pipeline
type: docker
name: node20
steps:
- name: install-deps
image: node:20
commands:
- npm install
- name: lint
image: node:20
depends_on:
- install-deps
commands:
- npm run lint
- name: build
image: node:20
depends_on:
- install-deps
commands:
- npm run build
- name: export
image: node:20
depends_on:
- build
commands:
- npm run export
- name: deploy-production
image: node:20
depends_on:
- export
environment:
SSH_KEY:
from_secret: DEPLOYMENT_SSH_KEY
commands:
- 'echo "$SSH_KEY" > /tmp/ssh_key'
- chmod 600 /tmp/ssh_key
- ssh -4 -i /tmp/ssh_key www@caffeine.csclub.uwaterloo.ca -o StrictHostKeyChecking=no '~/bin/classprofile/deploy-2023.sh'
when:
branch:
- main
trigger:
event:
exclude:
- pull_request # avoid double build on PRs

24
.eslintrc.json Normal file
View File

@ -0,0 +1,24 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": ["./tsconfig.json"]
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:import/typescript",
"plugin:react/recommended",
"plugin:prettier/recommended",
"next"
],
"plugins": ["@typescript-eslint", "react", "react-hooks", "prettier", "unused-imports"],
"settings": {
"react": {
"version": "detect"
}
}
}

38
.gitignore vendored Normal file
View File

@ -0,0 +1,38 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
.csc-git
# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

15
.prettierrc Normal file
View File

@ -0,0 +1,15 @@
{
"tabWidth": 2,
"useTabs": false,
"printWidth": 160,
"singleQuote": false,
"trailingComma": "all",
"arrowParens": "always",
"bracketSameLine": true,
"bracketSpacing": true,
"endOfLine": "lf",
"jsxSingleQuote": false,
"quoteProps": "as-needed",
"singleAttributePerLine": false,
"semi": true
}

3
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"recommendations": ["dbaeumer.vscode-eslint", "rvest.vs-code-prettier-eslint", "esbenp.prettier-vscode", "eamodio.gitlens"]
}

19
README.md Normal file
View File

@ -0,0 +1,19 @@
## Local Development
Make sure you have Node 18+ and NPM installed.
To run this locally, make sure you first install everything using `npm i` and then run `npm run dev` to start the project on localhost. If you need to use a different port than the default (`3000`), you can do `PORT=5000 npm run dev`.
To use ESLint, run `npm run lint` to get linter warnings and errors. You can also do `npm run lint:fix` to automatically fix any errors that can be corrected by the linter.
## Previewing a Production Deployment
To build the project, run `npm run build`. This will also give you linter warnings/errors. Then, use `npm start` to run the built project. You can also do `npm run preview` to do both together. Again, you can do `PORT=5000 npm start` or `PORT=5000 npm run preview`.
## Contributing
Implement changes on your own branch. The preferred branch naming scheme is `name/ticket/description`; for example, `alex/CSP-1234/fix-the-bug`, but this isn't really a big deal and won't be enforced.
The `main` branch is protected and requires a PR with one approval to merge to it. When reviewing PRs, look for the automatic deployment from Vercel which allows you to inspect the development preview without needing to clone and run the branch locally. Once you push to `main`, your changes will be automatically deployed to https://class-profile-2023.vercel.app/.
Make sure you assign a ticket to yourself before you start working on it to avoid conflicts/duplicate work. Please update the status as well so everyone can keep track of what's going on and people can ask to take over tickets if they want a task and notice you haven't started.

7
app/academics/layout.tsx Normal file
View File

@ -0,0 +1,7 @@
import { title } from "@/utils/title";
import React, { PropsWithChildren } from "react";
export const metadata = title("Academics");
const Layout: React.FC<PropsWithChildren> = ({ children }) => children;
export default Layout;

757
app/academics/page.tsx Normal file
View File

@ -0,0 +1,757 @@
"use client";
import { BarGraphHorizontal, BarGraphVertical } from "@/components/BarGraph";
import { BodyLink } from "@/components/BlankLink";
import { BottomNav } from "@/components/BottomNav";
import { ComponentWrapper } from "@/components/ComponentWrapper";
import { Header } from "@/components/Header";
import { PieChart } from "@/components/PieChart";
import { QuotationCarousel } from "@/components/QuotationCarousel";
import { SectionHeader } from "@/components/SectionHeader";
import { SectionWrapper } from "@/components/SectionWrapper";
import { StackedBarGraphHorizontal, StackedBarGraphVertical } from "@/components/StackedBarGraph";
import { WordCloud } from "@/components/WordCloud";
import {
A1,
A10,
A11,
A12,
A12i,
A12iKeys,
A13,
A13i,
A13ii,
A13iii,
A14,
A15,
A16,
A17,
A17Keys,
A18,
A19,
A2,
A20,
A20i,
A20ii,
A20iii,
A20iv,
A21,
A22,
A23,
A24,
A24i,
A24ii,
A24iii,
A24iv,
A25,
A26,
A3,
A4,
A5,
A6,
A7,
A8,
A9,
} from "@/data/academics";
import { pageRoutes } from "@/data/routes";
import { Color } from "@/utils/Color";
import { DefaultProp, barGraphMargin, barGraphProps, barGraphWidth, pieChartProps, wordCloudWidth } from "@/utils/defaultProps";
import { useWindowDimensions } from "@/utils/getWindowDimensions";
import { useIsMobile } from "@/utils/isMobile";
import styles from "../basePage.module.css";
export default function Academics() {
const pageWidth = useWindowDimensions().width;
const isMobile = useIsMobile();
return (
<div className={styles.page}>
<Header />
<SectionHeader title="Academics" />
<SectionWrapper title="Courses" />
<p style={{ paddingLeft: "4rem" }}>
<b>Note:</b> Only courses that showed up in more than one response were included, otherwise there would be too many courses to display properly.
</p>
<ComponentWrapper
heading="Is your expected graduation date the same as when you enrolled in your current program?"
bodyText={
<p>
Even though the vast majority of respondents stayed on track with their initial plans, it is also perfectly normal to deviate from the planned route
for a degree. Some students may have either shortened their degree by, for example, removing co-op from their degree or taking more classes than a
full course load per term. Meanwhile, others may have delayed their graduation by retaking failed classes, taking gap years, adding minors to their
degree, etc.
</p>
}
align="left">
<div className={styles.graphContainer}>
<PieChart data={A1} {...pieChartProps(isMobile, pageWidth, true)} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="What category of electives for your degree did you enjoy most?"
bodyText={
<>
<p>
Because of the breadth and depth requirements for UW&apos;s computer science degrees, students are required to take electives in varying subject
areas. Out of the different elective categories, communications and humanities courses were the most preferred, followed by courses in the social
sciences.
</p>
<p>
The popularity of these subject areas is likely due to the content taught in these courses being vastly different from the content in the required
math and computer science courses, as well as their lower difficulty, allowing for a more refreshing studying experience.
</p>
</>
}
align="right"
noBackground>
<BarGraphHorizontal data={A2} width={barGraphWidth(isMobile, pageWidth)} height={DefaultProp.graphHeight} margin={{ ...barGraphMargin, left: 180 }} />
</ComponentWrapper>
<ComponentWrapper
heading="Which CS course was your favourite?"
bodyText={
<p>
There is a large variety of favoured CS courses by this class, but the most popular is{" "}
<BodyLink href="https://uwflow.com/course/cs486">CS 486</BodyLink>, which provides an introduction to artificial intelligence, exploring an
extremely popular niche of computer science in today&apos;s society. Tied for second place are{" "}
<BodyLink href="https://uwflow.com/course/cs241">CS 241</BodyLink>, which teaches the relationship between high-level programming languages and
computer architecture, and <BodyLink href="https://uwflow.com/course/cs246">CS 246</BodyLink>, which introduces object-oriented programming, which
is a fundamental concept used in many areas of computer science.
</p>
}
align="left"
wordCloud>
<WordCloud
data={A3}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={30}
minFrequency={2}
background
/>
</ComponentWrapper>
<ComponentWrapper
heading="Which CS course was your least favourite?"
bodyText={
<>
<p>
<BodyLink href="https://uwflow.com/course/cs245">CS 245</BodyLink> was, by far, the least favourite CS class taken by the class of 2023. This is
likely due to its difficulty and the course focusing more on theory than application, as well as its lack of application outside of class despite
being a core CS course. As of October 2023 on UWFlow, the course has a 28% liked rating, demonstrating its lack of popularity.
</p>
<p>
<BodyLink href="https://uwflow.com/course/cs251">CS 251</BodyLink> comes in second, its content being about computer organization and design,
including the teaching of low-level languages and hardware. Although it is not very liked by this class, it actually has a 65% liked rating on
UWFlow, making it a bit more well-liked overall compared to this year.
</p>
</>
}
align="right"
noBackground
wordCloud>
<WordCloud
data={A4}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={30}
minFrequency={2}
/>
</ComponentWrapper>
<ComponentWrapper
heading="Which non-CS course was your favourite?"
bodyText={
<p>
There is a wide variety of favoured non-math electives by this year&apos;s class, with{" "}
<BodyLink href="https://uwflow.com/course/music246">MUSIC 246</BodyLink>, which explores music in film,{" "}
<BodyLink href="https://uwflow.com/course/music140">MUSIC 140</BodyLink>, which teaches various aspects of 20th century popular culture, and{" "}
<BodyLink href="https://uwflow.com/course/econ212">ECON 212</BodyLink>, exploring game theory, being, in order, the top 3 favourites!
</p>
}
align="left"
wordCloud>
<WordCloud
data={A5}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={30}
minFrequency={2}
background
/>
</ComponentWrapper>
<ComponentWrapper
heading="Which non-CS course was your least favourite?"
bodyText={
<p>
<BodyLink href="https://uwflow.com/course/stat231">STAT 231</BodyLink> was the least favourite non-CS course by a large margin. This course teaches
the fundamentals of statistics, however, it is not very popular due to the heavy load of content taught. As of October 2023, it has a 37% liked rate
on UWFlow. <BodyLink href="https://uwflow.com/course/spcom225">SPCOM 225</BodyLink> (rebranded to COMMST 225), which teaches interviewing, is also
not very popular amongst this class, coming in second in least favoured.
</p>
}
align="right"
noBackground
wordCloud>
<WordCloud
data={A6}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={30}
minFrequency={2}
/>
</ComponentWrapper>
<ComponentWrapper
heading="What is the hardest course you have taken?"
bodyText={
<p>
Coming in first place, the hardest course for many students was <BodyLink href="https://uwflow.com/course/math239">MATH 239</BodyLink>, which is a
mandatory course that provides an introduction to combinatorics, teaching graph theory and combinatorial analysis. Tied for second place in
difficulty amongst this class are <BodyLink href="https://uwflow.com/course/cs343">CS 343</BodyLink>, which explores concurrent and parallel
programming, and <BodyLink href="https://uwflow.com/course/cs350">CS 350</BodyLink>, which explores various aspects of operating systems.
</p>
}
align="left"
wordCloud>
<WordCloud
data={A7}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={30}
minFrequency={2}
background
/>
</ComponentWrapper>
<ComponentWrapper
heading="What is the easiest course you have taken?"
bodyText={
<p>
The easiest course that many computer science students have taken, by a large margin, is{" "}
<BodyLink href="https://uwflow.com/course/clas104">CLAS 104</BodyLink>, which explores Greco-Roman mythology. Coming in second, this year&apos;s
class also found <BodyLink href="https://uwflow.com/course/cs449">CS 449</BodyLink> to be an easy course, which is a course that provides an
introduction to human-computer interaction.
</p>
}
align="right"
noBackground
wordCloud>
<WordCloud
data={A8}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={30}
minFrequency={2}
/>
</ComponentWrapper>
<ComponentWrapper
heading="Which course do you regret taking most?"
bodyText={
<p>
The course that most students regret taking the most is <BodyLink href="https://uwflow.com/course/cs448">CS 448</BodyLink>, which teaches the
fundamentals of the inner workings of database systems. Tied for second place are{" "}
<BodyLink href="https://uwflow.com/course/econ101">ECON 101</BodyLink>, which teaches the basics of economics and microeconomics, and{" "}
<BodyLink href="https://uwflow.com/course/cs348">CS 348</BodyLink>, which, like CS 448, explores database management. It seems as though database
management is not the favourite subject topic of this year&apos;s computer science students!
</p>
}
align="left"
wordCloud>
<WordCloud
data={A9}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={8}
desktopMaxFontSize={60}
desktopMinFontSize={15}
minFrequency={2}
mobileMaxFontSize={60}
background
/>
</ComponentWrapper>
<ComponentWrapper
heading="Which course did you find the most useful?"
bodyText={
<p>
By far, this graduating year&apos;s students found the <BodyLink href="https://uwflow.com/course/cs246">CS 246</BodyLink> and{" "}
<BodyLink href="https://uwflow.com/course/cs341">CS 341</BodyLink> courses to be the most useful. CS 246 explores object-oriented programming, which
is applicable in many computer science-related topics, and is also one of the most favoured courses by this year&apos;s class. CS 341 also teaches a
topic that can be applied to all areas of computer science, which is algorithms and algorithm design.
</p>
}
align="right"
noBackground
wordCloud>
<WordCloud
data={A10}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={11}
desktopMaxFontSize={80}
mobileMaxFontSize={70}
minFrequency={2}
/>
</ComponentWrapper>
<ComponentWrapper
heading="Which course did you find the most useless?"
bodyText={
<p>
<BodyLink href="https://uwflow.com/course/cs245">CS 245</BodyLink>, which explores logic and how it is used in computation, was considered the most
useless course by most of this year&apos;s computer science class. This is followed by{" "}
<BodyLink href="https://uwflow.com/course/pd11">PD 11</BodyLink>, which teaches skills for report-writing. These two courses have a 28% and a 5%
liked rating, respectively, on UWFlow as of October 2023, further showing that they are not very popular courses amongst the students.
</p>
}
align="left"
wordCloud>
<WordCloud
data={A11}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={20}
desktopMaxFontSize={80}
mobileMaxFontSize={80}
minFrequency={2}
background
/>
</ComponentWrapper>
<ComponentWrapper
heading="Did you take any advanced/enriched courses?"
bodyText={
<>
<p>
37% of this year&apos;s class has taken at least one advanced or enriched course, while 63% has not. Advanced and enriched courses are regarded to
be much more difficult and require a larger time commitment than regular honours courses, which can already be difficult for many students!
</p>
<p>
However, for those who are looking for a challenge or are curious about math or computer science topics beyond those taught in the regular
courses, taking the advanced/enriched courses can be worth it for them. Moreover, for some students, their enjoyment of a course may depend on the
structure, and may choose between the regular courses and the advanced/enriched ones based on that factor.
</p>
</>
}
align="right"
noBackground>
<div className={styles.graphContainer}>
<PieChart data={A12} {...pieChartProps(isMobile, pageWidth)} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="If you took any advanced or enriched courses, for each course please indicate how much you enjoyed it?"
bodyText={
<>
<p>
The advanced/enriched courses are overall relatively popular amongst those who took them, with mostly all high ratings. There seems to be a
relatively constant number of people who took these courses over the years, meaning that it is likely that those who took advanced/enriched
courses enjoyed them and continued to take these courses after first year.
</p>
<p>
In general, it is recommended to try these courses out early if you&apos;re interested in them to see if they&apos;re suited for you before the
workload for your study term starts becoming more difficult to keep up with.
</p>
</>
}
align="left">
<StackedBarGraphHorizontal
width={isMobile ? pageWidth / 1.5 : 600}
height={DefaultProp.graphHeight}
keys={A12iKeys}
colorRange={[Color.primaryAccent, Color.secondaryAccentLight, Color.primaryAccentLighter]}
data={A12i.map(({ category, values }) => {
const total = values.reduce((x, y) => x + y);
return { category, ...Object.fromEntries(A12iKeys.map((k, i) => [k, +((values[i] * 100) / total)])) };
})}
margin={{ ...barGraphMargin, ...{ left: 100 } }}
displayPercentage
/>
</ComponentWrapper>
<SectionWrapper title="Transfer" />
<ComponentWrapper
heading="Did you transfer into your current program?"
bodyText={
<p>
29% of students in this year&apos;s class transferred into the program that they are currently in, which is a relatively high percentage. It can be
assumed that most of the students that transferred into their program transferred into CS, as it can be extremely difficult to transfer into CS/BBA
or CFM after their initial admissions for incoming first-year students from high school.
</p>
}
align="right"
noBackground>
<div className={styles.graphContainer}>
<PieChart data={A13} {...pieChartProps(isMobile, pageWidth, false)} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="What program did you transfer from?"
bodyText={
<>
<p>
Most of the students who transferred into computer science from a different program transferred from either Honours Mathematics or Software
Engineering.
</p>
<p>
Math and CS share many courses in the first year of the program, thus many Math students may have realized that they have a passion for computer
science and transferred into the program.
</p>
<p>
Software Engineering and CS are programs in which the students eventually end up in similar jobs and post-grad roles, thus, some of them may have
chosen to transfer to CS for a slightly less rigorous workload compared to that required by the Engineering faculty.
</p>
</>
}
align="left">
<div className={styles.graphContainer}>
<BarGraphHorizontal data={A13i} {...barGraphProps(isMobile, pageWidth, true)} margin={{ ...barGraphMargin, ...{ left: 120 } }} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="What term did you transfer into your program?"
bodyText={
<p>
The majority of students who transferred did so during their 2A term, followed by the number of transfers in 2B and 3A tying for second place. This
is likely due to students re-evaluating their academic and career pathway after experiencing around a year or more in their initial program.
</p>
}
align="right"
noBackground>
<div className={styles.graphContainer}>
<BarGraphVertical data={A13ii} {...barGraphProps(isMobile, pageWidth, false)} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="What were your reason(s) behind transferring?"
bodyText={
<p>
A major reason behind why many of the students transferred into computer science was because they were not as interested in their previous major
compared to their current one. Two other popular reasons for students transferring into computer science were to improve future job prospects and to
have a more flexible schedule and course requirements.
</p>
}
align="left">
<div className={styles.graphContainer}>
<BarGraphHorizontal
data={A13iii}
widthAlternatingLabel={1000}
alternatingLabelSpace={200}
lowerLabelDy="60px"
{...barGraphProps(isMobile, pageWidth, true)}
margin={{ ...barGraphMargin, ...{ left: 180 } }}
/>
</div>
</ComponentWrapper>
<SectionWrapper title="Terms and Averages" />
<ComponentWrapper
heading="Who is your favourite professor at UW?"
bodyText={
<p>
Three of the most popular professors amongst this year&apos;s class are <BodyLink href="https://uwflow.com/professor/alice_gao">Alice Gao</BodyLink>
, <BodyLink href="https://uwflow.com/professor/lesley_istead">Lesley Istead</BodyLink>, and{" "}
<BodyLink href="https://uwflow.com/professor/jeff_avery">Jeff Avery</BodyLink>. However, there is a wide variety of favoured professors amongst this
class, and we would like to express our thanks and give an honourable mention to every single one who has dedicated their time and energy towards
teaching us and enabling us to grow and thrive!
</p>
}
align="right"
noBackground
wordCloud>
<WordCloud
data={A14}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={3}
desktopMaxFontSize={75}
mobileMaxFontSize={48}
minFrequency={2}
/>
</ComponentWrapper>
<ComponentWrapper
heading="Which study term did you think was the hardest?"
bodyText={
<p>
Second year seemed to be the most difficult for the most students, with 2A, followed by 2B, being considered the most difficult study terms. This
could be due to that many of the least favoured courses and courses considered to be the most difficult, such as CS 245 and MATH 239, would have
been taken during the students&apos; 2A or 2B study term.
</p>
}
align="left">
<BarGraphVertical data={A15} {...barGraphProps(isMobile, pageWidth, true)} />
</ComponentWrapper>
<ComponentWrapper
heading="Which study term did you think was the easiest?"
bodyText={
<>
<p>
The 4A and 4B study terms were considered to be the easiest study terms by a large margin. This is likely due to most of the more difficult core
courses being finished already and students being able to take electives that they are more interested in once all the mandatory courses had been
completed.
</p>
<p>
This statistic highlights that even though classes may get harder (in 2A and 2B), it will get better after it gets worse, and that we should
persevere through the challenges that may arise during our undergraduate careers!
</p>
</>
}
align="right"
noBackground>
<BarGraphVertical data={A16} {...barGraphProps(isMobile, pageWidth, false)} />
</ComponentWrapper>
<ComponentWrapper heading="What was your average each term?" align="left">
<StackedBarGraphVertical
width={600}
height={400}
keys={A17Keys}
colorRange={[
Color.primaryAccentLighter,
Color.secondaryAccentLighter,
Color.secondaryAccentLight,
Color.primaryAccentLight,
Color.primaryAccent,
Color.primaryAccentDark,
Color.primaryAccentDarker,
]}
data={A17}
margin={barGraphMargin}
displayPercentage
/>
</ComponentWrapper>
<ComponentWrapper heading="What is your cumulative average?" align="left" noBackground>
<BarGraphHorizontal data={A18} width={barGraphWidth(isMobile, pageWidth)} height={DefaultProp.graphHeight} margin={barGraphMargin} />
<span>mean: 86.137 | min: 70 | Q1: 80.99 | median: 88 | Q3: 91.14 | max: 96.53</span>
</ComponentWrapper>
<ComponentWrapper heading="What is your faculty average?" align="right">
<BarGraphHorizontal data={A19} width={barGraphWidth(isMobile, pageWidth)} height={DefaultProp.graphHeight} margin={barGraphMargin} background />
<span>mean: 86.402 | min: 65.26 | Q1: 82.355 | median: 88 | Q3: 92 | max: 97.4</span>
</ComponentWrapper>
<ComponentWrapper
heading="Did you complete an option, specialization and/or minor?"
bodyText={
<p>
43% of respondents did complete an option, specialization, and/or minor during their undergraduate career. These are different ways in which you can
customize and add to your degree, depending on what electives you decide to take!
</p>
}
align="left"
noBackground>
<div className={styles.graphContainer}>
<PieChart data={A20} {...pieChartProps(isMobile, pageWidth, false)} />
</div>
</ComponentWrapper>
<ComponentWrapper heading="Which option(s) did you complete?" align="right" wordCloud>
<WordCloud
data={A20i}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={30}
background
/>
</ComponentWrapper>
<ComponentWrapper heading="Which minor(s) did you complete?" align="right" noBackground>
<WordCloud
data={A20ii}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={30}
/>
</ComponentWrapper>
<ComponentWrapper heading="Which specialization(s) did you complete?" align="left" wordCloud>
<WordCloud
data={A20iii}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={30}
background
/>
</ComponentWrapper>
<ComponentWrapper heading="What made you want to complete the option, specialization, and/or minor?" align="left" noBackground>
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={A20iv} circleDiameter={0} height={300} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="How many overloaded terms did you take (6 or more courses in one term)?"
bodyText={
<p>
59% of respondents did not take any overloaded terms. Overloading your term can be very challenging, as it increases your workload greatly. However,
it is still possible, as 27% of all of the respondents overloaded one or two terms, while 13% overloaded 3 or more terms, with some of them
overloading 6 terms!
</p>
}
align="right">
<BarGraphVertical data={A21} {...barGraphProps(isMobile, pageWidth, true)} />
</ComponentWrapper>
<ComponentWrapper
heading="How many courses have you failed?"
bodyText={
<p>
Most of the class completed their degree without failing any courses, at 83% of the respondents, but given that some of them did fail at least one
course but still obtained their degree, it&apos;s not the end if you fail one or a few of your courses!
</p>
}
align="left"
noBackground>
<div className={styles.graphContainer}>
<BarGraphVertical data={A22} {...barGraphProps(isMobile, pageWidth, false)} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="How many midterms/finals have you failed?"
bodyText={
<p>
Like previously, most of the class did not fail any midterms or finals, at 65% of the respondents, but this number is a lot lower than the number of
people who did not fail any courses, meaning that even if you do fail a large exam, it doesn&apos;t mean that you will fail your course - as long as
you put in the effort for the rest of the course. Regardless, no matter if you fail one or a few exams, it&apos;s still not over!
</p>
}
align="right">
<BarGraphVertical data={A23} {...barGraphProps(isMobile, pageWidth, true)} />
</ComponentWrapper>
<SectionWrapper title="Exchange" />
<ComponentWrapper
heading="Did you take any exchange terms?"
bodyText={
<p>
Most of the class did not take any exchange terms, but a small minority, at 9% of respondents, did. Taking an exchange term is an opportunity for
students to study for a term in a completely different environment, in a foreign country, that they can start applying to in their second year.
</p>
}
align="left"
noBackground>
<div className={styles.graphContainer}>
<PieChart data={A24} {...pieChartProps(isMobile, pageWidth, false)} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="What term did you take an exchange in?"
bodyText={
<p>
It seems as though taking an exchange term is popular later on in this year&apos;s students&apos; undergraduate careers, as 91% of those who took an
exchange term took it in either term 4A or 4B.
</p>
}
align="right">
<div className={styles.graphContainer}>
<PieChart data={A24i} {...pieChartProps(isMobile, pageWidth, true)} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="Where did you take your exchange term?"
bodyText={
<p>
The most popular country in which students took an exchange term was Singapore, followed by Switzerland and the Netherlands. Even though various
students took an exchange term in the same country, they generally attended different schools, with the two most popular universities being the
National University of Singapore and the Technical University of Delft (in the Netherlands).
</p>
}
align="left"
noBackground>
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={A24ii} circleDiameter={0} height={300} />
</div>
</ComponentWrapper>
<ComponentWrapper heading="What was the hardest thing about going on exchange?" align="right">
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={A24iii} circleDiameter={0} height={300} />
</div>
</ComponentWrapper>
<ComponentWrapper heading="What is your favourite memory from your time during the exchange?" align="right" noBackground>
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={A24iv} circleDiameter={0} height={300} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="What residence did you live in your first year?"
bodyText={
<p>
Most of the respondents lived at Village 1 during their first year, at 31% of the class. This is followed by UW Place in second place, at 16%, and
Ron Eydt Village in third, at 9% of the class. This makes sense, as these are three of the largest capacity residences on campus, with V1 holding
1300+ residents, UW Place holding 1600+ residents, and REV holding almost 1000 residents.
</p>
}
align="left"
wordCloud>
<WordCloud
data={A25}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={60}
mobileMaxFontSize={30}
background
/>
</ComponentWrapper>
<ComponentWrapper
heading="Have you done a URA (Undergraduate Research Assistantship)?"
bodyText={
<p>
While the majority of the class has not done a URA, 20% of them have undertaken an URA, which is a program that allows students to undertake a
10-week part-time research opportunity during a study term.
</p>
}
align="right"
noBackground>
<div className={styles.graphContainer}>
<PieChart data={A26} {...pieChartProps(isMobile, pageWidth, false)} />
</div>
</ComponentWrapper>
<BottomNav leftPage={pageRoutes.demographics} rightPage={pageRoutes.computerScienceExperience} />
</div>
);
}

34
app/basePage.module.css Normal file
View File

@ -0,0 +1,34 @@
.page {
display: flex;
flex-direction: column;
justify-content: center;
}
.graphContainer {
padding: 0 calc(70rem / 16);
}
.quotationCarouselContainer {
display: flex;
flex-direction: column;
gap: calc(48rem / 16);
margin: calc(32rem / 16);
}
@media screen and (max-width: 1200px) {
.graphContainer {
padding: 0 calc(40rem / 16);
}
}
@media screen and (max-width: 1100px) {
.graphContainer {
padding: 0 calc(20rem / 16);
}
}
@media screen and (max-width: 900px) {
.graphContainer {
padding: 0;
}
}

View File

@ -0,0 +1,7 @@
import { title } from "@/utils/title";
import React, { PropsWithChildren } from "react";
export const metadata = title("CS Experience");
const Layout: React.FC<PropsWithChildren> = ({ children }) => children;
export default Layout;

View File

@ -0,0 +1,197 @@
"use client";
import { BarGraphHorizontal, BarGraphVertical } from "@/components/BarGraph";
import { BottomNav } from "@/components/BottomNav";
import { ComponentWrapper } from "@/components/ComponentWrapper";
import { Header } from "@/components/Header";
import { PieChart } from "@/components/PieChart";
import { SectionHeader } from "@/components/SectionHeader";
import { WordCloud } from "@/components/WordCloud";
import { E1, E2, E3, E4, E5, E6, E7, E8 } from "@/data/computer-science-experience";
import { pageRoutes } from "@/data/routes";
import { DefaultProp, barGraphMargin, barGraphProps, barGraphWidth, pieChartProps, wordCloudWidth } from "@/utils/defaultProps";
import { useWindowDimensions } from "@/utils/getWindowDimensions";
import { useIsMobile } from "@/utils/isMobile";
import styles from "../basePage.module.css";
export default function Academics() {
const pageWidth = useWindowDimensions().width;
const isMobile = useIsMobile();
return (
<div className={styles.page}>
<Header />
<SectionHeader title="CS Experience" subtitle="Learn about the Computer Science Experience of the graduating class" />
<ComponentWrapper
heading="Which of the following coding experiences did you have prior to university?"
bodyText={
<>
<p>
Coding experience prior to university can be valuable however is not something anyone is required to have to be a part of the CS program at
Waterloo. However, these opportunities are a great way to help decide whether CS or programming is worth for you to pursue when coming to
university.
</p>
<p>
Hence, the majority of respondents have experience taking a CS course in high school. Many students have also participated in coding competitions
or hackathons. Waterloo offers a variety of coding competitions/hackthons like CCC and Hack the North. Many early LC grinders were a part of the
graduating class as well.
</p>
</>
}
align="left">
<BarGraphHorizontal
data={E1}
width={barGraphWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
margin={{ ...barGraphMargin, ...{ left: 200 } }}
background
/>
</ComponentWrapper>
<ComponentWrapper
heading="How many programming languages do you know?"
bodyText={
<p>
Most students claim they know 5+ languages (including Racket maybe). This is evidently due to students having the opportunity to learn a variety of
skills through different classes, internships, and external opportunities like hackahtons over the course of their university career. Allowing
students to gain both breadth and depth across a variety of fields, syntax, and paradigms.
</p>
}
align="right"
noBackground>
<div className="center-col">
<BarGraphVertical data={E2} {...barGraphProps(isMobile, pageWidth)} />
<span>mean: 5.915 | min: 0 | Q1: 4 | median: 6 | Q3: 8 | max: 10</span>
</div>
</ComponentWrapper>
<ComponentWrapper
heading="What is your favourite programming language?"
bodyText={
<p>
The majority of students seem to favour Python and C++ as their favourite languages, with Python enjoyers being the majority. This doesn&apos;t come
as a surprise as both are heavily supported and used in either course content or in the field. Shout out to the 1 Haskell enjoyer and the 2 Racket
enjoyers.
</p>
}
align="left"
wordCloud>
<WordCloud
data={E3}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={8}
desktopMaxFontSize={75}
mobileMaxFontSize={48}
background
/>
</ComponentWrapper>
<ComponentWrapper
heading="What is your favourite text editor or IDE?"
bodyText={
<>
<p>
VS Code once again, at no surprise, is the favourite code editor for the class of 2023. A versatile and customizable code editor that simplifies
any task with a variety of open-source extensions available to take on any project.
</p>
<p>
VS Code is fast, lightweight, easy to use, powerful with its extensions, and offers a plethora of themes. We are sad to say that the class of 2023
does not have any Microsoft Word enjoyers-a heavily customizable text editor.
</p>
</>
}
align="right"
noBackground
wordCloud>
<WordCloud
data={E4}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={8}
desktopMaxFontSize={75}
mobileMaxFontSize={48}
/>
</ComponentWrapper>
<ComponentWrapper
heading="What operating system(s) do you mainly use?"
bodyText={
<>
<p>
Each of these 3 operating systems provides their own benefits and downsides, however making the right choice comes down to personal preference and
comfort for daily. The majority of the respondents are split between Windows and MacOS, with 81 students developing on MacOS.
</p>
<p>
Additionally, it seems that UNIX-based OS (MacOS/Linux) are predominantly used by students, due to the various tools and features that they cater
to programmers.
</p>
</>
}
align="left">
<div className={styles.graphContainer}>
<PieChart data={E5} {...pieChartProps(isMobile, pageWidth, true)} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="What is your LeetCode proficiency level?"
bodyText={
<p>
The majority of respondents have a proficiency level of medium problems when it comes to doing Leetcode problems. Many students also have little to
no experience with leetcode. Leetcode is a platform that provides individuals with various coding problems that can be a great way to prep for
various coding interviews.
</p>
}
align="right"
noBackground>
<div className={styles.graphContainer}>
<PieChart data={E6} {...pieChartProps(isMobile, pageWidth)} {...{ labelTextSize: 20 }} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="How many side projects have you completed during university, if any?"
bodyText={
<>
<p>
Side projects are a great way to pick up new skills, build your resume for internships, or explore fields you are interested in. Having a few side
projects can greatly help with getting internship opportunities.
</p>
<p>
Over 30% of students have completed 3 or more side projects during their time at Waterloo. With the majority of students having done 2 or fewer
during their time at university.
</p>
</>
}
align="left">
<div className="center-col">
<BarGraphVertical data={E7} {...barGraphProps(isMobile, pageWidth, true)} lowerLabelDy="0" />
<span>mean: 2.467 | min: 0 | Q1: 1 | median: 2 | Q3: 3 | max: 10</span>
</div>
</ComponentWrapper>
<ComponentWrapper
heading="How many hackathons in total have you attended as a hacker?"
bodyText={
<>
<p>
Hackathons are a great way to meet new people, learn new skills, or just bring ideas to life. There are various club or committee-hosted Hackathon
opportunities for any skill level at Waterloo and even around the world for students to participate in.
</p>
<p>69% (nice) of students have had the chance to attend a hackathon during prior to graduating CS at Waterloo.</p>
</>
}
align="right"
noBackground>
<div className="center-col">
<BarGraphVertical data={E8} {...barGraphProps(isMobile, pageWidth)} />
<span>mean: 2.837 | min: 0 | Q1: 1 | median: 2 | Q3: 3 | max: 23</span>
</div>
</ComponentWrapper>
<BottomNav leftPage={pageRoutes.academics} rightPage={pageRoutes.coop} />
</div>
);
}

View File

@ -0,0 +1,7 @@
import { title } from "@/utils/title";
import React, { PropsWithChildren } from "react";
export const metadata = title("Contributors");
const Layout: React.FC<PropsWithChildren> = ({ children }) => children;
export default Layout;

93
app/contributors/page.tsx Normal file
View File

@ -0,0 +1,93 @@
"use client";
import { BottomNav } from "@/components/BottomNav";
import { Header } from "@/components/Header";
import { Panel } from "@/components/Panel";
import { SectionHeader } from "@/components/SectionHeader";
import { CPWebDevs, communityReps, designers } from "@/data/contributors";
import { pageRoutes } from "@/data/routes";
import styles from "../basePage.module.css";
interface ContributorProfile {
name: string;
link: string;
}
interface ContributorGroupProps {
group: Array<ContributorProfile>;
}
function ContributorGroup({ group }: ContributorGroupProps) {
return (
<ul>
{group
.sort((a, b) => a.name.localeCompare(b.name))
.map((d, idx) => {
return (
<li key={idx}>
{d.link ? (
<a href={d.link} target="_blank" rel="noreferrer">
{d.name}
</a>
) : (
<a href="#" onClick={(e) => e.preventDefault()}>
{d.name}
</a>
)}
</li>
);
})}
</ul>
);
}
export default function Contributors() {
return (
<div className={styles.page}>
<Header />
<SectionHeader
title="Contributors"
subtitle="Huge thanks to all CSC members who have contributed to creating the first ever uWaterloo CS class profile!"
/>
<Panel>
<p>
The 2023 CS Class Profile was completed by members of the UW Computer Science Club. Specifically, several current and past members (as of this
writing) of the Community Representatives, Designers, Class Profile Web Developers, and Systems Committee put lots of time into making it what it is.
Please contact <a href="mailto: exec@csclub.uwaterloo.ca">exec@csclub.uwaterloo.ca</a> for specific concerns for the CS Class Profile, but the
specific contributors include the following:
</p>
<ul>
<li>
Community Representatives
<ContributorGroup group={communityReps} />
</li>
<li>
Designers
<ContributorGroup group={designers} />
</li>
<li>
Class Profile Web Developers
<ContributorGroup group={CPWebDevs} />
</li>
{/* <li>
Systems Committee
<ContributorGroup group={sysCom} />
</li> */}
</ul>
<p>
Furthermore, special thanks to former CSC President and Vice President,{" "}
<a href="https://www.linkedin.com/in/kallentu/" target="_blank" rel="noreferrer">
Kallen Tu
</a>{" "}
and{" "}
<a href=" https://www.linkedin.com/in/gordonle/" target="_blank" rel="noreferrer">
Gordon Le
</a>
, for kickstarting the existence of the CS Class Profile and for providing feedback! Note there may be other anonymous contributors on any of the
teams or committees, but their names are not listed here.
</p>
</Panel>
<BottomNav leftPage={pageRoutes.personal} rightPage={pageRoutes.home}></BottomNav>
</div>
);
}

7
app/coop/layout.tsx Normal file
View File

@ -0,0 +1,7 @@
import { title } from "@/utils/title";
import React, { PropsWithChildren } from "react";
export const metadata = title("Co-op");
const Layout: React.FC<PropsWithChildren> = ({ children }) => children;
export default Layout;

289
app/coop/page.tsx Normal file
View File

@ -0,0 +1,289 @@
"use client";
import { BarGraphVertical } from "@/components/BarGraph";
import { BottomNav } from "@/components/BottomNav";
import { BoxPlot } from "@/components/Boxplot";
import { ComponentSwitcher } from "@/components/ComponentSwitcher";
import { ComponentWrapper } from "@/components/ComponentWrapper";
import { Header } from "@/components/Header";
import { LineGraph } from "@/components/LineGraph";
import { PieChart } from "@/components/PieChart";
import { SectionHeader } from "@/components/SectionHeader";
import { StackedBarGraphHorizontal, StackedBarGraphVertical } from "@/components/StackedBarGraph";
import { WordCloud } from "@/components/WordCloud";
import { C1, C2, C3, C4, C5, C6i, C6ii, C6iii, C6iv, C6ix, C6ixKey, C6v, C6vi, C6viKey, C6vii, C6viiKey, C6viii, C6x, C6xKey } from "@/data/coop";
import { pageRoutes } from "@/data/routes";
import { Color } from "@/utils/Color";
import { DefaultProp, barGraphMargin, barGraphProps, pieChartProps, wordCloudWidth } from "@/utils/defaultProps";
import { useWindowDimensions } from "@/utils/getWindowDimensions";
import { useIsMobile } from "@/utils/isMobile";
import styles from "../basePage.module.css";
export default function Coop() {
const pageWidth = useWindowDimensions().width;
const isMobile = useIsMobile();
const colorRange = [Color.primaryAccent, Color.secondaryAccentLight, Color.primaryAccentLight];
const colorRange2 = [Color.primaryAccent, Color.secondaryAccentLight, Color.primaryAccentLight, Color.secondaryAccent, Color.primaryAccentLighter];
return (
<div className={styles.page}>
<Header />
<SectionHeader title="Co-op" subtitle="Explore careers, gain experience and earn money through UWaterloo's co-op program!" />
{/* C1 */}
<ComponentWrapper
heading="Are you in a co-op program?"
bodyText={
<p>
Out of the 135 individuals that participated in this class profile, 128 were in a co-op program and 7 were not. Most students choose to be in the
co-op program because of the great experiences it provides!
</p>
}
align="left">
<div className={styles.graphContainer}>
<PieChart data={C1} {...pieChartProps(isMobile, pageWidth, true)} />
</div>
</ComponentWrapper>
{/* C2 */}
<ComponentWrapper
heading=" What was your favourite co-op location?"
bodyText={
<p>
There is a variety of favoured co-op locations, with some of the most popular being New York, Toronto, San Francisco, and various other cities in
California.
</p>
}
align="right"
noBackground
wordCloud>
<WordCloud
data={C2}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight * 0.7}
wordPadding={15}
desktopMaxFontSize={75}
mobileMaxFontSize={48}
/>
</ComponentWrapper>
{/* c3 */}
<ComponentWrapper
heading="Have you ever had a co-op term without a placement?"
bodyText={
<>
<p>
About 18% of respondents have had at least one co-op term without a placement. If you&apos;re also in thie situation and cannot find one,
don&apos;t worry; you&apos;re not alone!
</p>
<p>
Finding a co-op placement, especially your first one, can be pretty difficult. As the recent pandemic also affected students in this year, it
could have also caused finding a placement to be even more difficult.
</p>
</>
}
align="left">
<div className={styles.graphContainer}>
<PieChart data={C3} {...pieChartProps(isMobile, pageWidth, true)} />
</div>
</ComponentWrapper>
{/* c4 */}
<ComponentWrapper
heading="Were you ever banned from WaterlooWorks for renegotiating an offer/match?"
bodyText={
<p>
Reneging an offer/match comes with its risks, but if you believe that your other offer is better, you can decide it to be worth it. Out of those who
participated in this class profile, about 6% of students were banned from WaterlooWorks for this activity.
</p>
}
align="right"
noBackground>
<div className={styles.graphContainer}>
<PieChart data={C4} {...pieChartProps(isMobile, pageWidth)} />
</div>
</ComponentWrapper>
{/* C5 */}
<ComponentWrapper
heading="How many co-op offers did you have rescinded?"
bodyText={
<p>
Majority of the participants, standing at 64%, did not rescind any co-op offers. If a participant did rescind any offers, they, for the most part,
only rescinded one, at 13% of the respondents, with very few rescinding more than one offer.
</p>
}
align="left">
<BarGraphVertical data={C5} {...barGraphProps(isMobile, pageWidth, true)} />
</ComponentWrapper>
{/* c6i */}
<ComponentWrapper heading="What company did you work for?" align="left" noBackground wordCloud>
<ComponentSwitcher
graphList={C6i.map((coopTerm, i) => (
<WordCloud
data={coopTerm}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={38}
key={i}
/>
))}
buttonList={C6i.map((_, i) => "Co-op #" + (i + 1).toString())}
/>
</ComponentWrapper>
{/* C6ii */}
<ComponentWrapper heading="Where were you located during work?" align="right">
<LineGraph
data={C6ii}
colorRange={colorRange2}
width={isMobile ? pageWidth / 1.5 : 600}
height={DefaultProp.graphHeight}
margin={{
top: 20,
bottom: 80,
left: 30,
right: 20,
}}
/>
</ComponentWrapper>
{/* C6iii */}
<ComponentWrapper heading="What was your position?" align="right" noBackground wordCloud>
<ComponentSwitcher
graphList={C6iii.map((coopTerm, i) => (
<WordCloud
data={coopTerm}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={38}
key={i}
/>
))}
buttonList={C6iii.map((_, i) => "Co-op #" + (i + 1).toString())}
/>
</ComponentWrapper>
{/* C6iv */}
<ComponentWrapper heading="What was your salary per hour in CAD (excluding other forms of compensation)?" align="left">
<BoxPlot
width={isMobile ? pageWidth / 1.5 : 500}
height={DefaultProp.graphHeight}
data={C6iv}
margin={{
top: 20,
left: 20,
}}
background
/>
</ComponentWrapper>
{/* C6v */}
<ComponentWrapper
heading="How much did you receive in other forms of compensation in CAD? (i.e. bonuses, stock options, relocation, housing, etc.)"
align="left"
noBackground>
<BoxPlot
width={isMobile ? pageWidth / 1.5 : 600}
height={DefaultProp.graphHeight}
data={C6v}
valueAxisLeftMargin={75}
margin={{
top: 20,
left: 20,
}}
/>
</ComponentWrapper>
{/* C6vi */}
<ComponentWrapper heading="What was your co-op evaluation rating?" align="right">
<div>
<StackedBarGraphHorizontal
width={isMobile ? pageWidth / 1.5 : 600}
height={DefaultProp.graphHeight}
keys={C6viKey}
colorRange={[Color.primaryAccent, Color.secondaryAccentLight, Color.primaryAccentLighter, Color.secondaryAccent]}
data={C6vi}
margin={barGraphMargin}
displayPercentage
tooltipBottomLabel="Co-op Term: "
/>
</div>
</ComponentWrapper>
{/* C7vi */}
<ComponentWrapper heading="How happy were you with your co-op during the work term specified?" align="left" noBackground>
<div>
<StackedBarGraphVertical
width={isMobile ? pageWidth / 1.5 : 600}
height={DefaultProp.graphHeight}
keys={C6viiKey}
colorRange={[Color.primaryAccent, Color.secondaryAccentLight, Color.primaryAccentLighter, Color.secondaryAccent, Color.primaryHeading]}
data={C6vii}
margin={barGraphMargin}
tooltipBottomLabel="Co-op Term: "
displayPercentage
/>
</div>
</ComponentWrapper>
{/* C6viii */}
<ComponentWrapper heading="How did you find your job?" align="left">
<div style={{ padding: "10px" }}>
<LineGraph
data={C6viii}
colorRange={colorRange}
width={isMobile ? pageWidth / 1.5 : 600}
height={DefaultProp.graphHeight}
margin={{
top: 20,
bottom: 80,
left: 30,
right: 20,
}}
/>
</div>
</ComponentWrapper>
{/* C6ix */}
<ComponentWrapper heading="Were you referred for the co-op?" align="left" noBackground>
<div>
<StackedBarGraphVertical
width={isMobile ? pageWidth / 1.5 : 600}
height={DefaultProp.graphHeight}
keys={C6ixKey}
colorRange={[Color.primaryAccent, Color.secondaryAccentLight]}
data={C6ix}
margin={barGraphMargin}
displayPercentage
tooltipBottomLabel="Co-op term: "
/>
</div>
</ComponentWrapper>
{/* C6x */}
<ComponentWrapper heading="Did you complete another co-op term after this?" align="right">
<div>
<StackedBarGraphVertical
width={isMobile ? pageWidth / 1.5 : 600}
height={DefaultProp.graphHeight}
keys={C6xKey}
colorRange={[Color.primaryAccent, Color.secondaryAccentLight]}
data={C6x}
margin={barGraphMargin}
displayPercentage
tooltipBottomLabel="Co-op term: "
/>
</div>
</ComponentWrapper>
<BottomNav leftPage={pageRoutes.computerScienceExperience} rightPage={pageRoutes.lifestyleAndInterests} />
</div>
);
}

View File

@ -0,0 +1,7 @@
import { title } from "@/utils/title";
import React, { PropsWithChildren } from "react";
export const metadata = title("Demographics");
const Layout: React.FC<PropsWithChildren> = ({ children }) => children;
export default Layout;

343
app/demographics/page.tsx Normal file
View File

@ -0,0 +1,343 @@
"use client";
import { BarGraphHorizontal, BarGraphVertical } from "@/components/BarGraph";
import { BodyLink } from "@/components/BlankLink";
import { BottomNav } from "@/components/BottomNav";
import { ComponentWrapper } from "@/components/ComponentWrapper";
import { Header } from "@/components/Header";
import { PieChart } from "@/components/PieChart";
import { SectionHeader } from "@/components/SectionHeader";
import { WordCloud } from "@/components/WordCloud";
import { D1, D10, D11, D12, D13, D14, D15, D16, D16i, D17, D18, D19, D2, D3, D4, D5, D6, D7, D8, D8i, D9 } from "@/data/demographics";
import { pageRoutes } from "@/data/routes";
import { DefaultProp, barGraphMargin, barGraphProps, barGraphWidth, pieChartProps, wordCloudWidth } from "@/utils/defaultProps";
import { useWindowDimensions } from "@/utils/getWindowDimensions";
import { useIsMobile } from "@/utils/isMobile";
import styles from "../basePage.module.css";
export default function Demographics() {
const pageWidth = useWindowDimensions().width;
const isMobile = useIsMobile();
return (
<div className={styles.page}>
<Header />
<SectionHeader title="Demographics" subtitle="An insight into the demographics of UW's CS programs" />
<ComponentWrapper
heading="What program are you in?"
bodyText={
<>
<p>
The 2023 class profile has a total of 135 respondents, with the majority of our class, 121 students, pursuing Computer Science. 7 of our talented
students are enrolled in the CS/BBA program, bringing their unique blend of technical and business knowledge to the class.
</p>
<p>
Additionally, seven students have chosen the CFM program, combining computer science with financial expertise, to explore the potentials that lie
in the world of FinTech. No matter your program, the UW CS Class of 2023 is a community of future tech leaders and problem solvers.
</p>
</>
}>
<div className={styles.graphContainer}>
<PieChart data={D1} {...pieChartProps(isMobile, pageWidth, true)} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="What is your gender identity?"
bodyText={
<>
<p>
The UW CS Class of 2023 proudly represents a spectrum of gender identities. However, unsurprisingly most of the representation is from men with 91
men and 42 women. This also includes a handful of individuals identifying as gender non-conforming, non-binary, or questioning.
</p>
<p>
Underrepresented gender identities are a popular topic in the tech community, so it is promising that more diverse people are becoming interested
in CS! Take a look at clubs such as <BodyLink href="https://wics.uwaterloo.ca/"> WiCS </BodyLink> and{" "}
<BodyLink href="https://www.techplusuw.com/"> Tech+</BodyLink> that address these issues and work to provide an inclusive environment in UW&apos;s
tech scene.
</p>
</>
}
align="right"
noBackground>
<div className={styles.graphContainer}>
<PieChart data={D2} {...pieChartProps(isMobile, pageWidth)} />
</div>
</ComponentWrapper>
<ComponentWrapper heading="What are your pronouns?">
<div className={styles.graphContainer}>
<PieChart data={D3} {...pieChartProps(isMobile, pageWidth, true)} labelTextSize={15} labelTextRadialOffset={-45} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="What is your birth year?"
bodyText={
<p>
The birth years of the UW CS Class of 2023 exhibit a range of generational diversity. The majority, 109 students, were born in the year 2000,
representing the bridge between the 20th and 21st centuries. 18 students were born between 1998, 1999, and 2001, highlighting the diversity in age
of a multi-generational graduating community within the field of computer science.
</p>
}
align="right"
noBackground>
<BarGraphVertical data={D4} {...barGraphProps(isMobile, pageWidth)} />
</ComponentWrapper>
<ComponentWrapper
heading="What is the racial category or categories with which you primarily identify?"
bodyText={
<>
<p>
The UW CS Class of 2023 is a dynamic blend of racial backgrounds, reflecting rich cultures and ethnicities. Our class comprises students from East
Asian, White, South Asian, Southeast Asian, Latin, Middle Eastern, and other racial backgrounds.
</p>
<p>
However, the majority, 92 students, identify as East Asian, including Chinese, Korean, Japanese, or other East Asian descent. This diverse mix
enriches our collective experiences and fosters a global perspective, strengthening our ability to tackle complex challenges in the field of
computer science with a more holistic worldview.
</p>
</>
}>
<BarGraphVertical data={D5} {...barGraphProps(isMobile, pageWidth, true)} />
</ComponentWrapper>
<ComponentWrapper
heading="What is your religion and/or spiritual affiliation?"
bodyText={
<p>
The class represents a wide array of religious and spiritual backgrounds. The majority of our class identifies as Agnostic or Atheist, reflecting
our strong emphasis on secular values. We also have a diverse mix of students practising Christianity, Hinduism, Buddhism, Islam, and other faiths.
Some students consider themselves to be spiritual in a general sense. Additionally, there are 18 students choosing not to specify their affiliation.{" "}
</p>
}
align="right"
noBackground>
<BarGraphHorizontal
data={D6}
width={barGraphWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
margin={{ ...barGraphMargin, ...{ left: 220 } }}
/>
</ComponentWrapper>
<ComponentWrapper
heading="What is the sexual identity or identities with which you identify?"
bodyText={
<p>
The UW CS Class of 2023 is a diverse group, with a significant 22% of our students identifying within the LGBTQ+ community. A majority, 117
students, identify as Heterosexual or straight. UW has plenty of groups that support the LGBTQ+ community that can be found
<BodyLink href="https://uwaterloo.ca/human-rights-equity-inclusion/equity-office/pride-uwaterloo"> here</BodyLink>. Clubs such as{" "}
<BodyLink href="https://www.techplusuw.com/"> Tech+ </BodyLink>
and <BodyLink href="https://ostem.clubs.wusa.ca/"> oSTEM </BodyLink>
support queer and trans students in tech and STEM environments!
</p>
}
align="left">
<BarGraphHorizontal
data={D7}
{...barGraphProps(isMobile, pageWidth, true)}
widthAlternatingLabel={700}
margin={{ ...barGraphMargin, ...{ left: 125 } }}
/>
</ComponentWrapper>
<ComponentWrapper
heading="How many languages are you fluent in?"
bodyText={
<>
<p>
The linguistic diversity within the UW CS Class of 2023 is impressive. A significant portion, 88 students, are fluent in two languages.
Additionally, 28 students are fluent in one language, while 13 students are fluent in three languages, highlighting their exceptional linguistic
skills. One student has a unique fluency in one and a half languages.
</p>
<p>
There&apos;s also one student with fluency in four languages, a remarkable accomplishment. This multilingualism enhances our class&apos;s global
perspective and strengthens our ability to collaborate on a global scale, reflecting the interconnected nature of the tech industry.
</p>
</>
}
align="right"
noBackground>
<BarGraphVertical data={D8} {...barGraphProps(isMobile, pageWidth)} />
</ComponentWrapper>
<ComponentWrapper
heading="Besides English, what languages are you fluent in?"
bodyText={
<p>
The multilingualism within the UW CS Class of 2023 is both diverse and impressive. Mandarin is the most widely spoken language, with 47 students
demonstrating fluency. Additionally, we have proficiency in French, with 19 students showing their skills. Other languages include Cantonese,
Russian, and Hindi, each spoken by several students. This diversity enriches our communication and understanding, making us a truly international
community
</p>
}
align="left"
wordCloud>
<WordCloud
data={D8i}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={48}
background
/>
</ComponentWrapper>
<ComponentWrapper
heading="What is your political alignment?"
bodyText={
<>
<p>
The data on political alignment within the UW CS Class of 2023 reveals a balanced distribution of political beliefs, with a slightly higher
representation of &apos;Moderate Left&apos; and &apos;Moderate&apos; alignments. This diversity of political views reflects the class&apos;s
ability to engage in open and nuanced discussions about various societal issues. It suggests an intellectually curious and tolerant class that
values a range of perspectives, encouraging constructive dialogues and problem-solving in an inclusive academic environment.
</p>
<p>
The presence of students across different points on the political spectrum also signifies the readiness to embrace a well-rounded understanding of
complex issues, an important attribute for future leaders in the tech industry, where ethical and societal considerations often intersect with
technology development.
</p>
</>
}
align="right"
noBackground>
<PieChart data={D9} {...pieChartProps(isMobile, pageWidth)} labelTextSize={15} labelTextRadialOffset={-30} />
</ComponentWrapper>
<ComponentWrapper
heading="Where did you live before coming to UW?"
bodyText={
<p>
A large population of students arrived in Waterloo from the GTA area prior to coming to Waterloo, with 77% of respondents residing in all of
Ontario. There are also a handful of students coming internationally from areas like Germany, Vietnam, Indonesia, and many more.
</p>
}
align="left"
wordCloud>
<WordCloud
data={D10}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={48}
background
/>
</ComponentWrapper>
<ComponentWrapper
heading="What is the highest education level of your parents?"
bodyText={
<p>
We see that almost 90% of respondents&apos; families have a bachelor&apos;s Degree or higher. Most parents of the graduating class have a
master&apos;s Degree. We will see if many of the graduating class plan to follow in the footsteps of their parents.
</p>
}
align="right"
noBackground>
<BarGraphVertical data={D11} {...barGraphProps(isMobile, pageWidth)} />
</ComponentWrapper>
<ComponentWrapper
heading="What was your family income before entering your current UW program?"
bodyText={
// <p>
// Most families made more than the average family income in Canada in 2020 (
// <BodyLink href="https://www150.statcan.gc.ca/t1/tbl1/en/tv.action?pid=1110001201">$104,350</BodyLink>) The range of 51k to 200k was the most common
// among families. To sustain a first-year tuition fee that can hover between $8,000 to $55,000, it would make sense for many families to rely on other
// sources of financial support.
// </p>
""
}
align="left">
<BarGraphHorizontal
// TODO: change when histogram component is ready
data={D12}
{...barGraphProps(isMobile, pageWidth, true)}
margin={{ ...barGraphMargin, left: 125 }}
/>
</ComponentWrapper>
<ComponentWrapper
heading="How many close relatives have attended UW?"
bodyText={
<p>
Most of the graduating class are the first family member in their extended family to have had the opportunity to attend and graduate from Waterloo.
Are you planning to recommend Waterloo to future students in your family.
</p>
}
align="right"
noBackground>
<BarGraphHorizontal data={D13} {...barGraphProps(isMobile, pageWidth)} lowerLabelDy="0" />
</ComponentWrapper>
<ComponentWrapper heading="What immigrant generation do you belong to?" align="left">
<div className={styles.graphContainer}>
<PieChart data={D14} {...pieChartProps(isMobile, pageWidth, true)} labelTextSize={20} labelTextRadialOffset={-45} />
</div>
</ComponentWrapper>
<ComponentWrapper heading="What was your high school admissions average?" align="left" noBackground>
<BarGraphVertical data={D15} {...barGraphProps(isMobile, pageWidth)} lowerLabelDy="0" />
<span>mean: 96.229 | min: 87 | Q1: 95 | median: 96.415 | Q3: 98 | max: 99.8</span>
</ComponentWrapper>
<ComponentWrapper
heading="Was your current program your first choice out of all of the programs you applied to in high school?"
bodyText={
<p>
The majority of respondents agreed that the UW CS programs were their first choice on OUAC during applications. Let&apos;s see if their hopes and
dreams panned out in the other sections{" "}
</p>
}
align="right">
<div className={styles.graphContainer}>
<PieChart data={D16} {...pieChartProps(isMobile, pageWidth, true)} labelTextSize={20} labelTextRadialOffset={-45} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="If not, what university did your first-choice program belong to?"
bodyText={
<p>
Seems like most students were hoping to be in other programs at the University of Waterloo (SE cough cough) but ended up settling on coming into CS
when they made their final decision. Another handful of students were aiming for a variety of American universities as well.
</p>
}
align="left"
noBackground>
<div className={styles.graphContainer}>
<BarGraphHorizontal data={D16i} {...barGraphProps(isMobile, pageWidth)} lowerLabelDy="0" margin={{ ...barGraphMargin, ...{ left: 150 } }} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="Which of the following specialized high school programs did you do?"
bodyText={
<p>
The majority of respondents seemed to have been in some specialized program at their high schools prior to university. With AP and IB programs being
the most popular choice for students prior to coming into Waterloo&apos;s CS program
</p>
}
align="right">
<BarGraphVertical data={D17} {...barGraphProps(isMobile, pageWidth, true)} lowerLabelDy="0" />
</ComponentWrapper>
<ComponentWrapper heading="How much money did you receive in UW in scholarships and grants?" align="right" noBackground>
<BarGraphHorizontal data={D18} {...barGraphProps(isMobile, pageWidth, true)} margin={{ ...barGraphMargin, left: 120 }} />
<span>mean: ~$7.85k | min: $0 | Q1: $2k | median: $4.5k | Q3: $10k | max: $93k</span>
</ComponentWrapper>
<ComponentWrapper heading="What is your MBTI type?" bodyText={<p>ESFP and ESTJ received no answers.</p>} align="left">
<BarGraphHorizontal data={D19} {...barGraphProps(isMobile, pageWidth, true)} />
</ComponentWrapper>
<BottomNav leftPage={pageRoutes.home} rightPage={pageRoutes.academics} />
</div>
);
}

BIN
app/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

7
app/full-time/layout.tsx Normal file
View File

@ -0,0 +1,7 @@
import { title } from "@/utils/title";
import React, { PropsWithChildren } from "react";
export const metadata = title("Full-time");
const Layout: React.FC<PropsWithChildren> = ({ children }) => children;
export default Layout;

159
app/full-time/page.tsx Normal file
View File

@ -0,0 +1,159 @@
"use client";
import { BarGraphHorizontal, BarGraphVertical } from "@/components/BarGraph";
import { BottomNav } from "@/components/BottomNav";
import { ComponentWrapper } from "@/components/ComponentWrapper";
import { Header } from "@/components/Header";
import { PieChart } from "@/components/PieChart";
import { SectionHeader } from "@/components/SectionHeader";
import { WordCloud } from "@/components/WordCloud";
import { F1, F2, F3, F4, F5, F6, F7 } from "@/data/full-time";
import { pageRoutes } from "@/data/routes";
import { DefaultProp, barGraphMargin, barGraphProps, pieChartProps, wordCloudWidth } from "@/utils/defaultProps";
import { useWindowDimensions } from "@/utils/getWindowDimensions";
import { useIsMobile } from "@/utils/isMobile";
import styles from "../basePage.module.css";
export default function FullTime() {
const pageWidth = useWindowDimensions().width;
const isMobile = useIsMobile();
return (
<div className={styles.page}>
<Header />
<SectionHeader title="Full-time" />
<ComponentWrapper
heading="What company will you be working for post-grad?"
bodyText={<p>Most students have secured full-time positions and will be working full time post-grad. This is more than 50% of respondents. </p>}
align="left"
wordCloud>
<WordCloud
data={F1}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={48}
background
/>
</ComponentWrapper>
<ComponentWrapper
heading="Where will you be working from post-grad?"
bodyText={
<>
<p>Toronto, Ontario, and New York are the two main places most people seem to be moving to start their new life as full-time adults!</p>
<p>
A majority of students said they will be working in the USA, which is no surprise due to most opportunities in the tech field being in tech hubs
like San Francisco, New York, and Seattle.
</p>
<p>Regardless, it just goes to show that if you work hard, and with just a bit of luck, you can work in your dream location!</p>
</>
}
align="right"
noBackground
wordCloud>
<WordCloud
data={F2}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={48}
/>
</ComponentWrapper>
<ComponentWrapper
heading="How many offers did you decide between? Please enter a number."
bodyText={<p>More than half of the respondents chose between 1 or 2 offers!</p>}
align="left">
<div className="center-col">
<BarGraphVertical data={F3} {...barGraphProps(isMobile, pageWidth, true)} />
<span>mean: 2.338 | min: 1 | Q1: 1 | median: 2 | Q3: 3 | max: 10</span>
</div>
</ComponentWrapper>
<ComponentWrapper
heading="Are you returning to a prior co-op?"
bodyText={
<>
<p>
59 out of 81 respondents are returning to a prior co-op on a permanent return offer! This statistic shows that a co-op program lets you test jobs
and find what team/company culture fits your liking much earlier in your career.
</p>
<p>Additionally, in these co-op positions, students can obtain new connections and leverage them for future full-time employment.</p>
</>
}
align="right"
noBackground>
<div className={styles.graphContainer}>
<PieChart data={F4} {...pieChartProps(isMobile, pageWidth)} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="If working in Canada, what will be your first-year total compensation (salary + signing + first-year stock + bonus) in CAD?"
bodyText={
<p>
The world of tech offers intriguing annual compensation and salary options. These compensation packages encompass a mix of components, including
salary, signing bonuses, first-year stock options, and more. Many of these salaries start high and will just continue rising as the years go by!
</p>
}
align="left">
<div className="center-col">
<BarGraphHorizontal data={F5} {...barGraphProps(isMobile, pageWidth, true)} margin={{ ...barGraphMargin, left: 112 }} />
<span>mean: ~$128k | min: $29k | Q1: $97k | median: $105k | Q3: $160k | max: $280k</span>
</div>
</ComponentWrapper>
<ComponentWrapper
heading="If working outside of Canada, what will be your first-year total compensation (salary + signing + first-year stock + bonus) in CAD?"
bodyText={
<>
<p>
For those working outside of Canada, with a majority of them working in the USA, their first-year total compensation is significantly higher than
working in Canada.
</p>
<p>
This disparity highlights the competitive nature of the international tech job market and the opportunities available for individuals willing to
explore opportunities abroad.
</p>
</>
}
align="right"
noBackground>
<div className="center-col">
<BarGraphHorizontal data={F6} {...barGraphProps(isMobile, pageWidth)} margin={{ ...barGraphMargin, left: 112 }} />
<span>mean: ~$372k | min: $170k | Q1: $270k | median: $300k | Q3: $485k | max: $850k</span>
</div>
</ComponentWrapper>
<ComponentWrapper
heading="What field/career path will you be in post-grad?"
bodyText={
<>
<p>
More than 60% of respondents are set to embark on their careers in software development! However, it is fascinating to see many others venturing
into diverse fields such as cloud computing, game development, and various others.
</p>
<p>Undergraduate is a time for individuals to discover their passions and chart the course for their future careers.</p>
</>
}
align="left"
wordCloud>
<WordCloud
data={F7}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={10}
desktopMaxFontSize={75}
mobileMaxFontSize={48}
background
/>
</ComponentWrapper>
<BottomNav leftPage={pageRoutes.postGrad} rightPage={pageRoutes.mentalHealth} />
</div>
);
}

238
app/globals.css Normal file
View File

@ -0,0 +1,238 @@
@font-face {
font-family: Lexend;
src: url(/fonts/Lexend-VariableFont_wght.ttf);
}
html {
scroll-behavior: smooth;
scroll-padding-top: calc(92rem / 16);
width: 100vw;
overflow-x: hidden;
}
@-moz-document url-prefix() {
/*
* Firefox has a bug relating to smooth scrolling
* https://github.com/vercel/next.js/issues/22858
*/
html {
scroll-behavior: auto;
}
}
body {
/* Theme colours */
--pink: #ef839d;
--light-pink: #faa3bd;
/* Above is New Header 1 Colour */
--lighter-pink: #ffe7e7;
--orange: #f5917b;
--light-orange: #ffc4a9;
--lighter-orange: #ffddcd;
--navy: #0b2041;
/* Above is New Background Colour */
--light-navy: #354265;
--dark-navy: #141d34;
--side-panel: #141d34;
--menu-icon: #e18e89;
--menu-icon-hover: #eaa9a6;
--menu-close-icon: #603e2f;
/* Chart colors */
--chart-blue-light: #3472a8;
--chart-blue-heavy: #559ad6;
--chart-yellow-light: #fff0bb;
--chart-yellow-heavy: #fbd961;
--chart-green-light: #0f9635;
--chart-green-heavy: #4bbc6b;
--chart-pink-light: #ba4366;
--chart-pink-heavy: #dd547d;
--chart-label: white;
/* Default is dark theme */
--light--primary-background: #ffffef;
--light--secondary-background: #fdf5ed;
--light--primary-accent: #ca634d;
--light--primary-accent-light: var(--orange);
--light--primary-accent-lighter: #ffbc9f;
--light--secondary-accent: #e55f98;
--light--translucent-accent: rgba(255, 231, 231, 0.75);
--light--secondary-accent-light: #fea0c8;
--light--primary-heading: #d02b53;
--light--primary-text: #483b35;
--light--link: var(--orange);
--light--link-hover: #ffbc9f;
--light--card-background: #ffffff;
--light--label: #a98778;
--dark--primary-background: var(--navy);
--dark--secondary-background: var(--dark-navy);
--dark--tertiary-background: var(--light-navy);
--dark--primary-accent: var(--pink);
--dark--primary-accent-light: var(--light-pink);
--dark--primary-accent-lighter: var(--lighter-pink);
--dark--primary-accent-dark: #dc538e;
--dark--primary-accent-darker: #c8417c;
--dark--secondary-accent: var(--orange);
--dark--secondary-accent-light: var(--light-orange);
--dark--secondary-accent-lighter: var(--lighter-orange);
--dark--translucent-accent: rgba(239, 131, 157, 0.75);
/* --dark--primary-heading: #ffc48d; */
--dark--primary-heading: #a1ccf2;
/* Above is New H2 */
/* --dark--secondary-heading: var(--pink); */
--dark--secondary-heading: #ef839d;
/* Above is New H3 */
--dark--link: var(--pink);
--dark--4-heading: #91f1ac;
/* Above is New H4 */
--dark--link-hover: var(--light-pink);
--dark--primary-text: #fdf9ec;
/* Above is New Primary Text */
--dark--secondary-text: var(--light-pink);
--dark--card-background: #2c3651;
--dark--label: #ffffff;
--dark--overlay: #000000;
--dark--primary-pink: #fe5f8f;
--primary-pink: var(--dark--primary-pink);
--dark--primary-yellow: #fbd961;
--primary-yellow: var(--dark--primary-yellow);
--primary-background: var(--dark--primary-background);
--secondary-background: var(--dark--secondary-background);
--tertiary-background: var(--dark--tertiary-background);
--primary-accent: var(--dark--primary-accent);
--primary-accent-light: var(--dark--primary-accent-light);
--primary-accent-lighter: var(--dark--primary-accent-lighter);
--primary-accent-dark: var(--dark--primary-accent-dark);
--primary-accent-darker: var(--dark--primary-accent-darker);
--secondary-accent: var(--dark--secondary-accent);
--secondary-accent-light: var(--dark--secondary-accent-light);
--secondary-accent-lighter: var(--dark--secondary-accent-lighter);
--translucent-accent: var(--dark--translucent-accent);
--primary-heading: var(--dark--primary-heading);
--secondary-heading: var(--dark--secondary-heading);
--link: var(--dark--link);
--link-hover: var(--dark--link-hover);
--primary-text: var(--dark--primary-text);
--card-background: var(--dark--card-background);
--label: var(--dark--label);
--label-overlay: var(--dark--overlay);
--navbar-background-rgb: 25, 27, 33;
background-color: var(--primary-background);
color: var(--primary-text);
font-family: "Lexend", sans-serif;
margin: 0;
position: relative;
/* Font styling for body */
font-size: calc(18rem / 16);
font-weight: 500;
}
/* Page titles (e.g. Demographics) */
h1 {
font-size: calc(48rem / 16);
font-weight: 700;
color: var(--primary-accent-light);
margin-top: calc(32rem / 16);
margin-bottom: calc(16rem / 16);
letter-spacing: 0.2rem;
}
/* Major section headings (e.g. About the Programs) */
h2 {
font-size: calc(36rem / 16);
font-weight: 700;
color: var(--primary-heading);
margin-top: calc(32rem / 16);
margin-bottom: calc(16rem / 16);
letter-spacing: 0.1rem;
}
/* Minor section headings & questions (e.g. What Program Are You In?) */
h3 {
font-size: calc(32rem / 16);
font-weight: 700;
color: var(--secondary-heading);
margin-top: calc(24rem / 16);
margin-bottom: calc(16rem / 16);
letter-spacing: 0.075rem;
}
/* Titles within paragraphs (e.g. About the Programs -> Computer Science)*/
h4 {
font-size: calc(26rem / 16);
font-weight: 700;
color: var(-dark--4-heading);
margin-top: calc(24rem / 16);
margin-bottom: calc(8rem / 16);
letter-spacing: 0.05rem;
}
p {
color: var(--primary-text);
margin-top: 0.75rem;
margin-bottom: 1.5rem;
line-height: 1.5rem;
}
a {
color: var(--link);
text-decoration: none;
transition: color 0.5s ease-out;
}
a:hover {
color: var(--link-hover);
}
@media only screen and (prefers-color-scheme: dark) {
body {
--primary-pink: var(--dark--primary-pink);
--primary-yellow: var(--dark--primary-yellow);
--primary-background: var(--dark--primary-background);
--secondary-background: var(--dark--secondary-background);
--tertiary-background: var(--dark--tertiary-background);
--primary-accent: var(--dark--primary-accent);
--primary-accent-light: var(--dark--primary-accent-light);
--primary-accent-lighter: var(--dark--primary-accent-lighter);
--primary-accent-dark: var(--dark--primary-accent-dark);
--secondary-accent: var(--dark--secondary-accent);
--secondary-accent-light: var(--dark--secondary-accent-light);
--secondary-accent-dark: var(--primary-accent-dark);
--primary-heading: var(--dark--primary-heading);
--secondary-heading: var(--dark--secondary-heading);
--link: var(--dark--link);
--link-hover: var(--dark--link-hover);
--primary-text: var(--dark--primary-text);
--card-background: var(--dark--card-background);
--label: var(--dark--label);
--label-overlay: var(--dark--overlay);
}
}
/* Custom styles for scroll bars on chromium */
::-webkit-scrollbar {
width: 1em;
height: 1em;
}
::-webkit-scrollbar-track,
::-webkit-scrollbar-track:horizontal {
background: var(--card-background);
}
::-webkit-scrollbar-thumb,
::-webkit-scrollbar-thumb:horizontal {
background-color: var(--tertiary-background);
}
.center-col {
display: flex;
flex-direction: column;
align-items: center;
}

View File

@ -0,0 +1,7 @@
import { title } from "@/utils/title";
import React, { PropsWithChildren } from "react";
export const metadata = title("Intimacy & Drugs");
const Layout: React.FC<PropsWithChildren> = ({ children }) => children;
export default Layout;

View File

@ -0,0 +1,260 @@
"use client";
import { BarGraphHorizontal, BarGraphVertical } from "@/components/BarGraph";
import { BottomNav } from "@/components/BottomNav";
import { ComponentWrapper } from "@/components/ComponentWrapper";
import { GroupedBarGraphHorizontal } from "@/components/GroupedBarGraph";
import { Header } from "@/components/Header";
import { PieChart } from "@/components/PieChart";
import { QuotationCarousel } from "@/components/QuotationCarousel";
import { SectionHeader } from "@/components/SectionHeader";
import { WordCloud } from "@/components/WordCloud";
import { I1, I10, I11, I12, I13, I2i, I2ii, I3, I4, I5, I6, I7, I8, I9i, I9ii, I9iii } from "@/data/intimacy-and-drugs";
import { pageRoutes } from "@/data/routes";
import { Color } from "@/utils/Color";
import { DefaultProp, barGraphMargin, barGraphProps, barGraphWidth, pieChartProps, wordCloudWidth } from "@/utils/defaultProps";
import { useWindowDimensions } from "@/utils/getWindowDimensions";
import { useIsMobile } from "@/utils/isMobile";
import styles from "../basePage.module.css";
export default function IntimacyAndDrugs() {
const pageWidth = useWindowDimensions().width;
const isMobile = useIsMobile();
return (
<div className={styles.page}>
<Header />
<SectionHeader title="Intimacy and Drugs" subtitle="What have people tried during university?" />
<ComponentWrapper
heading="Which drugs have you tried?"
bodyText={
<>
<p>
Most students experience substances for the first time during university. The common ones we see students try are marijuana, alcohol, and tobacco,
with most staying away from the harder drugs.
</p>
<p>Make sure to stay safe and be in a safe environment when trying any type of drug.</p>
</>
}
align="left">
<GroupedBarGraphHorizontal
className={styles.barGraphDemo}
data={I1}
barColors={[Color.chartGreenLight, Color.chartBlueLight, Color.chartPinkLight]}
barHoverColorsMap={{
[Color.chartGreenLight]: Color.chartGreenHeavy,
[Color.chartBlueLight]: Color.chartBlueHeavy,
[Color.chartPinkLight]: Color.chartPinkHeavy,
}}
width={barGraphWidth(isMobile, pageWidth)}
minWidth={700}
height={DefaultProp.graphHeight}
margin={{ ...barGraphMargin, ...{ left: 200, bottom: 60 } }}
/>
</ComponentWrapper>
<ComponentWrapper
heading="Have you ever had sexual intercourse?"
bodyText={
<>
<p>
University is a time when many students are finally living alone or with friends and have more freedom in their lives. No more curfews, no more
parents wondering where they are, and because of this, many students seek out new relationships and explore their sexuality.
</p>
<p>There is no need to rush, and it is important to take your time and be comfortable before taking this step.</p>
</>
}
align="right"
noBackground>
<div className={styles.graphContainer}>
<BarGraphVertical data={I2i} {...barGraphProps(isMobile, pageWidth)} lowerLabelDy="0" />
</div>
</ComponentWrapper>
<ComponentWrapper heading="If so, in which term did you first have sexual intercourse?">
<div className={styles.graphContainer}>
<BarGraphVertical data={I2ii} {...barGraphProps(isMobile, pageWidth, true)} lowerLabelDy="0" />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="How many relationships have you been in during university?"
bodyText={<p>The majority of our respondents have been in either 1 or 2 relationships during their undergraduate career.</p>}
align="right"
noBackground>
<div className="center-col">
<BarGraphVertical data={I3} {...barGraphProps(isMobile, pageWidth)} lowerLabelDy="0" />
<span>mean: 1.2 | min: 0 | Q1: 0 | median: 1 | Q3: 2 | max: 7</span>
</div>
</ComponentWrapper>
<ComponentWrapper
heading="How many sexual partners have you had during university?"
bodyText={
<p>
Most respondents have had one sexual partner during their university with an almost equal number having zero. But nothing can top the one who
reported having 57...
</p>
}
align="left">
<div className="center-col">
<BarGraphVertical data={I4} {...barGraphProps(isMobile, pageWidth, true)} lowerLabelDy="0" />
<span>mean: 2.623 | min: 0 | Q1: 0 | median: 1 | Q3: 2 | max: 57</span>
</div>
</ComponentWrapper>
<ComponentWrapper
heading="How much time did you spend in a relationship during university?"
bodyText={
<p>
Maintaining relationships during university can sometimes be difficult with heavy course loads, however, if there is a will there&apos;s a way! Most
relationships tend to last 2-4 years, with 21 of them making it past the 4 year mark. Congratulations!
</p>
}
align="right"
noBackground>
<BarGraphHorizontal
data={I5}
width={barGraphWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
margin={{ ...barGraphMargin, ...{ left: 100 } }}
/>
</ComponentWrapper>
<ComponentWrapper
heading="Have you ever cheated on someone, been cheated on, or helped someone cheat?"
bodyText={<p>Almost all respondents have never been in any cheating situations.</p>}
align="left">
<div className={styles.graphContainer}>
<BarGraphVertical data={I6} {...barGraphProps(isMobile, pageWidth, true)} lowerLabelDy="0" />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="Did you ever date another CS / CS/BBA / CFM student?"
bodyText={<p>Most respondents have not dated another CS/ CS/BBA / CFM student. 42 students reported having done so, while 74 said they did not.</p>}
align="right"
noBackground>
<div className={styles.graphContainer}>
<PieChart data={I7} {...pieChartProps(isMobile, pageWidth)} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="If you answered no to the previous question, did you want to date another CS / CS/BBA / CFM student?"
bodyText={
<p>
Regarding those who answered no, 40 out of the 66 respondents said that they would not. Is this surprising to you? Dating someone in your program
means you now have someone to spend those all-nighters with. On the other hand, having a class with your ex after a bad breakup can definitely be
awkward.
</p>
}
align="left">
<div className={styles.graphContainer}>
<PieChart data={I8} {...pieChartProps(isMobile, pageWidth, true)} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="Are you currently in a relationship?"
bodyText={
<p>
59 respondents reported being in a relationship and 58 said they were not. Let&apos;s hope that the 18 who did not respond are not in complicated
relationships.
</p>
}
align="right"
noBackground>
<PieChart data={I9i} {...pieChartProps(isMobile, pageWidth, false)} />
</ComponentWrapper>
<ComponentWrapper
heading="In which term did you meet your current partner?"
bodyText={
<p>
Before university and during 1A seem to be the times most people fall in love and meet their current partners. But regardless, who knows, maybe this
term is your time to shine!
</p>
}
align="left">
<BarGraphVertical data={I9ii} {...barGraphProps(isMobile, pageWidth, true)} lowerLabelDy="0" />
</ComponentWrapper>
<ComponentWrapper
heading="Where did you meet your current partner?"
bodyText={
<p>
For those who had a current partner, most of them met them through mutual friends, with high school being in second. Mutual friends are a great way
to meet new people and it helps to create even larger friend groups!
</p>
}
align="right"
noBackground
wordCloud>
<WordCloud
data={I9iii}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={30}
/>
</ComponentWrapper>
<ComponentWrapper
heading="What is your rice purity score?"
bodyText={
<p>
For those uninformed, the Rice Purity test is a 100-question survey that aims to gauge a person&apos;s level of innocence or their experience in
regard to a variety of scenarios ranging from sexual situations to substances and various others. 5 respondents had the same score of 50! Out of all
respondents, 8 was our lowest (???) and 100 (a perfectly pure score!) was our highest.
</p>
}
align="left"
wordCloud>
<div className="center-col">
<WordCloud
data={I10}
width={wordCloudWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={30}
background
/>
<span>mean: 58.411 | min: 8 | Q1: 42 | median: 54 | Q3: 73 | max: 100</span>
</div>
</ComponentWrapper>
<ComponentWrapper
heading="How has your understanding of relationships changed during university?"
bodyText={
<p>
Relationships are often a major turning point in many people&apos;s lives. It is a commitment to each othersome struggle, while others do not.
Let&apos;s see what other people have to say.
</p>
}
align="right"
noBackground>
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={I11} circleDiameter={0} width={barGraphWidth(isMobile, pageWidth)} height={isMobile ? 600 : 500} />
</div>
</ComponentWrapper>
<ComponentWrapper heading="Any advice for people looking for a relationship?" bodyText={<p>How does one get rizz?</p>} align="left">
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={I12} circleDiameter={0} width={barGraphWidth(isMobile, pageWidth)} height={600} />
</div>
</ComponentWrapper>
<ComponentWrapper heading="Any advice for people already in a relationship?" align="right" noBackground>
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={I13} circleDiameter={0} width={barGraphWidth(isMobile, pageWidth)} height={600} />
</div>
</ComponentWrapper>
<BottomNav leftPage={pageRoutes.lifestyleAndInterests} rightPage={pageRoutes.postGrad} />
</div>
);
}

9
app/layout.tsx Normal file
View File

@ -0,0 +1,9 @@
import "./globals.css";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}

View File

@ -0,0 +1,7 @@
import { title } from "@/utils/title";
import React, { PropsWithChildren } from "react";
export const metadata = title("Lifestyle & Interests");
const Layout: React.FC<PropsWithChildren> = ({ children }) => children;
export default Layout;

View File

@ -0,0 +1,383 @@
"use client";
import { BarGraphHorizontal, BarGraphVertical } from "@/components/BarGraph";
import { BottomNav } from "@/components/BottomNav";
import { ComponentWrapper } from "@/components/ComponentWrapper";
import { Header } from "@/components/Header";
import { PieChart } from "@/components/PieChart";
import { SectionHeader } from "@/components/SectionHeader";
import { WordCloud } from "@/components/WordCloud";
import { L1, L10, L11, L12, L13, L14, L15, L16, L17, L18, L19, L2, L20, L21, L3, L4, L5, L6, L7, L8, L9 } from "@/data/lifestyle-and-interests";
import { pageRoutes } from "@/data/routes";
import { DefaultProp, barGraphMargin, barGraphProps, barGraphWidth, pieChartProps } from "@/utils/defaultProps";
import { useWindowDimensions } from "@/utils/getWindowDimensions";
import { useIsMobile } from "@/utils/isMobile";
import styles from "../basePage.module.css";
export default function LifestyleAndInterests() {
const pageWidth = useWindowDimensions().width;
const isMobile = useIsMobile();
return (
<div className={styles.page}>
<Header />
<SectionHeader title="Lifestyle and Interests" subtitle="What did the class of 2023 do in their free time?" />
<ComponentWrapper
heading="How did your outlook on religion change during university?"
bodyText={
<p>
Similar to previous years, most students were never religious. Of those that remained the same, however, there was a portion of students who were
previously religious but are no longer.
</p>
}
align="left">
<BarGraphHorizontal data={L1} {...barGraphProps(isMobile, pageWidth, true)} margin={{ ...barGraphMargin, left: 200 }} />
</ComponentWrapper>
<ComponentWrapper
heading="Did you learn how to cook during university?"
bodyText={
<>
<p>
Cooking is often a challenge for many new university students. Having lived in the comfort of home for so long, learning to cook is a new struggle
that many face.
</p>
<p>
However, UW CS students have adapted to overcome this struggle, with 83 of the 135 learning how to cook during university! Only 10 have never
learned how to cook, with the rest already having prior knowledge.
</p>
</>
}
align="right"
noBackground>
<div className={styles.graphContainer}>
<PieChart data={L2} {...pieChartProps(isMobile, pageWidth)} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="How frequently did you cook for yourself?"
bodyText={
<p>
Practice makes perfect, especially with cooking. Most students cook for themselves every week with a handful never doing so. Other students fall
into the categories of every few weeks, monthly, or once every few months.
</p>
}
align="left">
<BarGraphVertical data={L3} {...barGraphProps(isMobile, pageWidth, true)} lowerLabelDy="0" />
</ComponentWrapper>
<ComponentWrapper
heading="How many days in a week were you physically active in a week?"
bodyText={
<p>
Just like in 2022, Waterloo students achieve excellence again by beating the stereotypes and being active several days per week. CS students know
when to code hard but also when it&apos;s time to go to the gym.
</p>
}
align="right"
noBackground>
<div className="center-col">
<BarGraphVertical data={L4} {...barGraphProps(isMobile, pageWidth)} lowerLabelDy="0" />
<span>mean: 3.129 | min: 1 | Q1: 2 | median: 3 | Q3: 4 | max: 7</span>
</div>
</ComponentWrapper>
<ComponentWrapper
heading="Did you feel like you had time to pursue your hobbies?"
bodyText={
<>
<p>
Contrary to last year, there was a significant difference between those who did and those who do not. This year, 76 said they either agreed or
strongly agreed, while 35 said they disagreed or strongly disagreed.
</p>
<p>Pursuing hobbies outside of school is a great way to de-stress and put your time and energy into something you love! </p>
</>
}
align="left">
<BarGraphVertical data={L5} {...barGraphProps(isMobile, pageWidth, true)} />
</ComponentWrapper>
<ComponentWrapper
heading="How often did you attend parties/gatherings?"
bodyText={
<>
<p>
Parties are a fun event to relieve stress, meet some new people, and dance the night away. Waterloo students are no exception and many students
like to attend a party every now and then.
</p>
<p>Whether it is to celebrate or find some new people, remember always to be safe and plan getting home!</p>
</>
}
align="right"
noBackground>
<BarGraphHorizontal
data={L6}
width={barGraphWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
margin={{ ...barGraphMargin, ...{ left: 210 } }}
/>
</ComponentWrapper>
<ComponentWrapper
heading="What time do you usually go to sleep?"
bodyText={
<p>
Sleep schedule? What&apos;s that? Waterloo students see the perfect sleeping time between 1 AM to 3 AM. Who wants to be an early bird when you can
be a night owl?{" "}
</p>
}
align="left">
<BarGraphVertical data={L7} {...barGraphProps(isMobile, pageWidth, true)} />
</ComponentWrapper>
<ComponentWrapper
heading="How many hours of sleep do you get on average per night?"
bodyText={
<p>
Sleep is very important! A healthy body is a healthy mind. Most students get 7+ hours every night! With the average time Waterloo students are
sleeping, and the amount of sleep they get, it is safe to say that not many people like morning classes.
</p>
}
align="right"
noBackground>
<div className="center-col">
<BarGraphVertical data={L8} {...barGraphProps(isMobile, pageWidth)} />
<span>mean: 7.229 | min: 0 | Q1: 7 | median: 7 | Q3: 8 | max: 12</span>
</div>
</ComponentWrapper>
<ComponentWrapper
heading="How often did you pull all-nighters throughout university?"
bodyText={
<>
<p>
To the lucky ones that haven&apos;t, those who have don&apos;t wish it upon you. Whether it be splashing cold water on your face, chugging down
energy drinks, or drinking cold coffee, one must do what they gotta do to stay awake.
</p>
<p>While 56 students have never pulled an all-nighter, about 70 students go through the struggle every few weeks or months.</p>
</>
}
align="left">
<BarGraphVertical data={L9} {...barGraphProps(isMobile, pageWidth, true)} />
</ComponentWrapper>
<ComponentWrapper
heading="While on campus, how many days of the week do you eat out at a restaurant?"
bodyText={
<p>
Whether it be at the Waterloo Plaza, King Street, or Uptown, Waterloo has a wide variety of restaurants for anything you are craving. We have
Waterloo icons like Lazeez still standing after so many years and new ones being opened every term. Make sure to check them out!{" "}
</p>
}
align="right"
noBackground>
<div className="center-col">
<BarGraphVertical data={L10} {...barGraphProps(isMobile, pageWidth)} lowerLabelDy="0" />
<span>mean: 2.992 | min: 0 | Q1: 2 | median: 3 | Q3: 4 | max: 7</span>
</div>
</ComponentWrapper>
<ComponentWrapper
heading="What is your favourite restaurant to go to on/around campus?"
bodyText={
<p>
Gol&apos;s Noodles seems to be many people&apos;s go-to restaurant in Waterloo. With its affordable prices and diverse menu, no wonder it&apos;s a
Waterloo favourite!
</p>
}
align="left"
wordCloud>
<WordCloud
data={L11}
width={isMobile ? pageWidth / 1.5 : 800}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={48}
minFrequency={2}
background
/>
</ComponentWrapper>
<ComponentWrapper
heading="Which extracurricular activities did you participate in?"
bodyText={
<p>
Waterloo has over 200+ clubs! Make sure to definitely check out clubs by finding their Instagram pages, and posters, or finding them during club
day! There is a club for almost everything, and if you can&apos;t find a club, start one!
</p>
}
align="right"
noBackground
wordCloud>
<WordCloud
data={L12}
width={isMobile ? pageWidth / 1.5 : 800}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={48}
minFrequency={2}
/>
</ComponentWrapper>
<ComponentWrapper
heading="Where is your favourite place to study on campus?"
bodyText={
<>
<p>
MC and DC seem to be student&apos;s favourite places to study on campus. This makes sense as most Math faculty students have most of their classes
in these two iconic buildings.
</p>
<p>Make sure to still explore different parts of campus every now and then to potentially find your new favourite place</p>
</>
}
align="left">
<BarGraphHorizontal
data={L13}
width={barGraphWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
margin={{ ...barGraphMargin, ...{ left: 60 } }}
background
/>
</ComponentWrapper>
<ComponentWrapper
heading="What are your hobbies?"
bodyText={
<p>
Waterloo students have a variety of hobbies, but video games and reading top them all! After a long day of leetcoding and math, coming home to hop
on a game with your friends or read a nice book makes the endless suffering just a little bit more worth it.
</p>
}
align="right"
noBackground
wordCloud>
<WordCloud
data={L14}
width={isMobile ? pageWidth / 1.5 : 800}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={48}
/>
</ComponentWrapper>
<ComponentWrapper
heading="How many different countries did you visit outside of Canada during university?"
bodyText={
<>
<p>
Waterloo students love to travel! During the breaks in between terms, getting an opportunity to visit a new country and potentially experience a
new culture is an unforgettable experience.
</p>
<p>Most Waterloo students have visited at least visited 1 country outside of Canada during their time here.</p>
</>
}
align="left">
<div className="center-col">
<BarGraphVertical data={L15} {...barGraphProps(isMobile, pageWidth, true)} lowerLabelDy="0" />
<span>mean: 2.556 | min: 0 | Q1: 1 | median: 1 | Q3: 3 | max: 22</span>
</div>
</ComponentWrapper>
<ComponentWrapper
heading="What is your favourite bubble tea restaurant in or around UW?"
bodyText={<p>The Alley and CoCo are most people&apos;s favourite bubble tea restaurants in or around Waterloo. What&apos;s your favourite drink?</p>}
align="right"
noBackground>
<BarGraphHorizontal
data={L16}
width={barGraphWidth(isMobile, pageWidth + 5)}
height={DefaultProp.graphHeight}
margin={{ ...barGraphMargin, ...{ left: 150 } }}
/>
</ComponentWrapper>
<ComponentWrapper
heading="What is your favourite shawarma restaurant in or around UW?"
bodyText={
<p>
Coming in first place is Shawarma Plus, with Lazeez in a close second, and iPotato in third. Shawarma is a popular Middle Eastern dish that often
consists of a choice of marinated meat, some form of carbs, and vegetables.
</p>
}
align="left">
<BarGraphHorizontal
data={L17}
width={barGraphWidth(isMobile, pageWidth)}
height={DefaultProp.graphHeight}
margin={{ ...barGraphMargin, ...{ left: 142 } }}
background
/>
</ComponentWrapper>
<ComponentWrapper
heading="How much time do you spend on the r/uwaterloo subreddit?"
bodyText={
<>
<p>
If you have ever had a question or want to meet some amazing other people, the r/uwaterloo subreddit is a great way to do so! Many students check
out the subreddit a few times a week or daily.
</p>
<p>Whether you have co-op questions, wondering what a good bird course is, or looking for a roommate, look no further than the UW subreddit!</p>
</>
}
align="right"
noBackground>
<BarGraphVertical data={L18} {...barGraphProps(isMobile, pageWidth)} lowerLabelDy="0" />
</ComponentWrapper>
<ComponentWrapper
heading="How many friends throughout university were also in CS / CS/BBA / CFM?"
bodyText={
<p>
Struggling to pass a course together with your friends is just a fun yet painful experience that you can&apos;t beat. Most Waterloo students have
friends in CS, CS/BBA, or CFM as many share the same classes together.
</p>
}
align="left">
<BarGraphVertical data={L19} {...barGraphProps(isMobile, pageWidth, true)} lowerLabelDy="0" />
</ComponentWrapper>
<ComponentWrapper
heading="How often do you keep in touch with high school friends?"
bodyText={
<p>
For students who travel far to come to Waterloo, keeping in touch with old high school friends can be tough. However, most Waterloo students do a
great job at this by regularly checking in and chatting with old friends.
</p>
}
align="right"
noBackground>
<BarGraphVertical data={L20} {...barGraphProps(isMobile, pageWidth)} lowerLabelDy="0" />
</ComponentWrapper>
<ComponentWrapper
heading="Where did you meet most of your friends?"
bodyText={
<p>
Although orientation can be a great time to meet people, most students find their friends from extracurriculars, mutual friends, and old friends
from high school. Although there is time to study, there&apos;s a time to touch some grass and meet some new people! Once university is over, the
knowledge learned may disappear, but the friendships built can last forever.
</p>
}
align="left"
wordCloud>
<WordCloud
data={L21}
width={isMobile ? pageWidth / 1.5 : 800}
height={DefaultProp.graphHeight}
wordPadding={7}
desktopMaxFontSize={75}
mobileMaxFontSize={48}
background
/>
</ComponentWrapper>
<BottomNav leftPage={pageRoutes.coop} rightPage={pageRoutes.intimacyAndDrugs} />
</div>
);
}

View File

@ -0,0 +1,7 @@
import { title } from "@/utils/title";
import React, { PropsWithChildren } from "react";
export const metadata = title("Mental Health");
const Layout: React.FC<PropsWithChildren> = ({ children }) => children;
export default Layout;

195
app/mental-health/page.tsx Normal file
View File

@ -0,0 +1,195 @@
"use client";
import { BarGraphVertical } from "@/components/BarGraph";
import { BottomNav } from "@/components/BottomNav";
import { ComponentWrapper } from "@/components/ComponentWrapper";
import { Header } from "@/components/Header";
import { PieChart } from "@/components/PieChart";
import { QuotationCarousel } from "@/components/QuotationCarousel";
import { SectionHeader } from "@/components/SectionHeader";
import { H1, H10, H11, H2, H3, H4, H5, H5i, H6, H7, H8, H9 } from "@/data/mental-health";
import { pageRoutes } from "@/data/routes";
import { barGraphProps, barGraphWidth, pieChartProps } from "@/utils/defaultProps";
import { useWindowDimensions } from "@/utils/getWindowDimensions";
import { useIsMobile } from "@/utils/isMobile";
import styles from "../basePage.module.css";
export default function MentalHealth() {
const pageWidth = useWindowDimensions().width;
const isMobile = useIsMobile();
return (
<div className={styles.page}>
<Header />
<SectionHeader title="Mental Health" />
<ComponentWrapper
heading="Have you struggled with mental health during undergrad?"
bodyText={
<p>
Mental health is a serious concern for many students. A majority of those surveyed have mentioned struggling with mental health issues during their
time in college. The university environment can often be a source of stress, anxiety, or other mental health problems. So, it&apos;s important to
take care of yourself and support each other during challenging moments.
</p>
}
align="left">
<div className={styles.graphContainer}>
<PieChart data={H1} {...pieChartProps(isMobile, pageWidth, true)} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="Have you ever experienced burnout?"
bodyText={
<p>
Burnout is quite prevalent among our respondents, with most individuals indicating they have encountered it at some point. The consistent workload
can easily lead to students feeling overwhelmed or emotionally exhausted. It&apos;s essential to recognize that these feelings are entirely normal
and to prioritize allowing yourself breaks.
</p>
}
align="right"
noBackground>
<div className={styles.graphContainer}>
<PieChart data={H2} {...pieChartProps(isMobile, pageWidth)} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="Have you ever been to therapy?"
bodyText={
<p>
Many people mentioned they haven&apos;t tried therapy, but quite a few have either gone for it or thought about it. This shows that university life
can be really tough, so it&apos;s crucial to reach out and use the resources available to take care of your mental and physical health!
</p>
}
align="left">
<BarGraphVertical data={H3} {...barGraphProps(isMobile, pageWidth, true)} lowerLabelDy="0" />
</ComponentWrapper>
<ComponentWrapper
heading="Have you ever been to counselling?"
bodyText={
<>
<p>
Counseling is something that quite a few people have either tried or thought about. It&apos;s a reassuring sign that many students are open to
getting help when they need it.
</p>
<p>
So, remember to take care of yourself, both mentally and emotionally it&apos;s an important step in looking out for your well-being during your
university journey.
</p>
</>
}
align="right"
noBackground>
<BarGraphVertical data={H4} {...barGraphProps(isMobile, pageWidth)} lowerLabelDy="0" />
</ComponentWrapper>
<ComponentWrapper
heading="Have you ever used UW Health Services for your mental health?"
bodyText={
<>
<p>
UW Health Services is a program that offers easily accessible medical services. It&apos;s wonderful to observe that a significant portion of our
respondents have availed themselves of these services for their well-being. We encourage the continued utilization of these valuable resources in
the future.
</p>
<p>
University life can be demanding, and seeking assistance from UW Health Services is a common and supportive choice. To schedule an appointment,
you can reach out to them at (519) 888-4096 or email hsforms@uwaterloo.ca if phone booking is not convenient for you. Taking care of your health
is a priority, and these services are here to assist you.
</p>
</>
}
align="left">
<div className={styles.graphContainer}>
<PieChart data={H5} {...pieChartProps(isMobile, pageWidth, true)} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="If so, how was your experience with UW Health Services?"
bodyText={
<p>
Our respondents have expressed diverse opinions and provided feedback on their encounters with UW Health Services. The majority of respondents have
given ratings falling within the 1-3 range
</p>
}
align="right"
noBackground>
<BarGraphVertical data={H5i} {...barGraphProps(isMobile, pageWidth)} lowerLabelDy="0" />
</ComponentWrapper>
<ComponentWrapper
heading="Overall, how would you rate your mental health over your entire undergraduate career? "
bodyText={
<p>
In general, most respondents rated their mental health throughout their undergraduate career as a 3 or 4 out of 5. It&apos;s encouraging to note
that the majority of scores are toward the higher end of the scale!
</p>
}
align="left">
<BarGraphVertical data={H6} {...barGraphProps(isMobile, pageWidth)} minWidth={700} lowerLabelDy="60px" valueAxisLabelOffset={0} background />
</ComponentWrapper>
<ComponentWrapper
heading="Please give any general comments about mental health in university."
bodyText={
<>
<p>
Given the significant impact of mental health concerns in the university setting, a substantial number of our respondents have shared their
thoughts on this matter.
</p>
<p>
Here, you will find some quotes from students that discuss how UW&apos;s environment influences students&apos; mental health and offer suggestions
for enhancing mental well-being.
</p>
</>
}
align="right"
noBackground>
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={H7} circleDiameter={0} width={barGraphWidth(isMobile, pageWidth)} height={500} />
</div>
</ComponentWrapper>
<ComponentWrapper heading="What do you do to help cope with your mental health issues?" align="left">
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={H8} circleDiameter={0} width={barGraphWidth(isMobile, pageWidth)} height={500} />
</div>
</ComponentWrapper>
<ComponentWrapper heading="What do you think UW can do better to accommodate your mental health?" align="center" noBackground>
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={H9} circleDiameter={0} width={barGraphWidth(isMobile, pageWidth)} height={500} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="How much of an effect has imposter syndrome played in your university life?"
bodyText={
<>
<p>
The impact of imposter syndrome on university life is a concerning issue. When asked to rate its influence on a scale of 1 to 5, the majority of
respondents selected 4 or 5, indicating that imposter syndrome has significantly affected their lives.
</p>
<p>
This highlights the need for greater awareness and support to help students address this syndrome and foster a greater sense of confidence in
themselves.
</p>
</>
}
align="right">
<BarGraphVertical data={H10} {...barGraphProps(isMobile, pageWidth)} lowerLabelDy="0" background />
</ComponentWrapper>
<ComponentWrapper heading="What has been your experience with imposter syndrome?" align="left" noBackground>
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={H11} circleDiameter={0} width={barGraphWidth(isMobile, pageWidth)} height={500} />
</div>
</ComponentWrapper>
<BottomNav leftPage={pageRoutes.fullTime} rightPage={pageRoutes.personal} />
</div>
);
}

221
app/page.module.css Normal file
View File

@ -0,0 +1,221 @@
.main {
display: flex;
flex-direction: column;
align-items: center;
}
.main > * {
margin-bottom: calc(65rem / 16);
}
.top {
margin: 0 10%;
position: relative;
}
.title {
margin-top: 12rem;
font-size: 600%;
background: linear-gradient(285deg, #fff0bb 34.7%, #faa3bd 79.88%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.space {
position: absolute;
right: 10%;
}
.planet {
position: absolute;
right: 10%;
}
.planetBody {
padding: 50px;
}
.planet img {
position: absolute;
}
.moon {
position: absolute;
right: 32px;
top: 300px;
}
.curves {
margin: 0;
padding: 0;
width: 100vw;
}
.topCurve {
position: absolute;
}
.bottomCurve {
margin-top: 320px;
margin-bottom: -400px;
}
@keyframes oscillate {
0% {
transform: translateY(10px);
}
80% {
transform: translateY(0);
}
100% {
transform: translateY(0);
}
}
.downButton {
position: absolute;
z-index: 10;
top: 80vh;
width: 50px;
animation: 0.75s ease 0s infinite alternate none running oscillate;
}
.viewButton {
background: none;
display: flex;
border: none;
font-size: calc(30rem / 16);
color: var(--primary-accent-light);
font-weight: 700;
font-family: "Lexend", sans-serif;
position: relative;
cursor: pointer;
padding: 0;
transition: color 0.5s ease-out;
}
.viewButton:hover {
color: var(--label);
}
.viewButton:after {
content: "";
position: absolute;
width: 100%;
height: calc(2rem / 16);
bottom: 0px;
background-color: var(--primary-accent-lighter);
cursor: pointer;
transition: background-color 0.5s ease-out;
}
.viewButton:hover:after {
background-color: var(--primary-accent-light);
}
@media screen and (max-width: 1600px) {
.title {
margin-top: 8rem;
font-size: 400%;
}
}
@media screen and (max-width: 1200px) {
.title {
margin-top: 6rem;
font-size: 320%;
}
}
@media screen and (max-width: 700px) {
.decoratorDots {
display: none;
}
.decoratorSolid {
display: none;
}
.titleImage {
top: 2vh;
}
.blurb {
right: 0;
top: 30vh;
margin: 0.5rem 0;
}
.blurb h1 {
font-size: calc(38rem / 16);
}
.blurb h3 {
font-size: calc(25rem / 16);
}
.viewButton {
font-size: calc(25rem / 16);
}
.top {
margin: 0 5%;
position: relative;
}
.title {
margin-top: 4rem;
font-size: 250%;
}
.space {
top: 225px;
right: 25%;
}
.planetBody {
padding: 24px;
width: 102px;
height: 102px;
}
.planetRing {
width: 150px;
height: 150px;
}
.moon {
position: absolute;
right: 12px;
top: 140px;
}
.moon img {
width: 30px;
height: 30px;
}
.topCurve {
position: absolute;
}
.bottomCurve {
margin-top: 100px;
margin-bottom: 175px;
}
}
@media screen and (max-width: 400px) {
.title {
margin-top: 2rem;
font-size: 200%;
}
}
.homeSectionsStyles {
width: 70vw;
max-width: 1000px;
}

77
app/page.tsx Normal file
View File

@ -0,0 +1,77 @@
import { About } from "@/components/About";
import { BodyLink } from "@/components/BlankLink";
import { Header } from "@/components/Header";
import { Panel } from "@/components/Panel";
import { Sections } from "@/components/Sections";
import { pageRoutes } from "@/data/routes";
import { title } from "@/utils/title";
import Image from "next/image";
import styles from "./page.module.css";
export const metadata = title("Home");
export default function Home() {
return (
<>
<Header />
<div className={styles.main}>
<div className={styles.top}>
<h1 className={styles.title}>UW Computer Science 2023 Class Profile</h1>
<div className={styles.space}>
<div className={styles.planet}>
<Image className={styles.planetRing} src="/images/planet-ring.svg" alt="Planet Ring" width={300} height={300} />
<Image className={styles.planetBody} src="/images/planet-body.svg" alt="Planet Body" width={200} height={200} />
</div>
<div className={styles.moon}>
<Image src="/images/moon.svg" alt="Moon" width={64} height={64} />
</div>
</div>
</div>
<div className={styles.curves}>
<Image className={styles.topCurve} src="/images/main-page-wide-curve.svg" alt="Wide Curve" width={1440} height={200} layout="responsive" />
<Image className={styles.bottomCurve} src="/images/main-page-narrow-curve.svg" alt="Narrow Curve" width={1440} height={200} layout="responsive" />
</div>
<a href="#about" className={styles.downButton}>
<svg viewBox="0 0 20 11">
<path d="M 0 0 L 10 10 L 20 0" style={{ stroke: "white", strokeWidth: 1, fill: "none" }}></path>
</svg>
</a>
<About />
<Panel>
<h1>Preface</h1>
<p>
The 2023 CS Class Profile consists of data relevant to CS, CFM, and CS/BBA students completing their undergrad in 2023. These were combined with the
knowledge that students in these programs tend to have similar experiences, as they share many core courses. In the standard co-op offering, CS and
CFM take 4 years and 2 terms to complete, while CS/BBA can take up to a full 5 years.
</p>
<p>
The University of Waterloo&apos;s computer science programs are known to be prestigious and well-known in Canada as well as across the world. As of
2022, it ties for first place in Maclean&apos;s university rankings, and 25th internationally as a subject by the QS World University rankings. For
prospective students or anyone who is interested in learning more about what the students are like, this CS Class Profile will attempt to answer
some of your questions, and you may even learn a thing or two you didn&apos;t expect!
</p>
<p>
According to the{" "}
<b>
<BodyLink href="https://uwaterloo.ca/institutional-analysis-planning/university-data-and-statistics/student-data/degrees-granted-0">
Institutional Analysis & Planning (IAP)
</BodyLink>
</b>
, there were a 629 graduates from CS, CFM, and CS/BBA, leading to a overall survey turnout of 21%. By program, this is a 22% turnout from CS
graduates, 12% turnout from CS/BBA graduates, and 32% turnout from CFM graduates.
</p>
<p>
The survey questions were approved by the IAP, where all University of Waterloo stakeholders that are interested in conducting a non-academic
research survey involving a large portion of the UW population are reviewed and approved. The entirety of the survey creation and data processing
was done by the{" "}
<b>
<BodyLink href="https://csclub.uwaterloo.ca">UW Computer Science Club</BodyLink>
</b>
, so please check us out if you enjoy what you see!
</p>
</Panel>
<Sections data={pageRoutes} className={styles.homeSectionsStyles} />
</div>
</>
);
}

7
app/personal/layout.tsx Normal file
View File

@ -0,0 +1,7 @@
import { title } from "@/utils/title";
import React, { PropsWithChildren } from "react";
export const metadata = title("Personal");
const Layout: React.FC<PropsWithChildren> = ({ children }) => children;
export default Layout;

81
app/personal/page.tsx Normal file
View File

@ -0,0 +1,81 @@
"use client";
import { BottomNav } from "@/components/BottomNav";
import { ComponentWrapper } from "@/components/ComponentWrapper";
import { Header } from "@/components/Header";
import { QuotationCarousel } from "@/components/QuotationCarousel";
import { SectionHeader } from "@/components/SectionHeader";
import { P1, P10, P2, P3, P4, P5, P6, P7, P8, P9 } from "@/data/personal";
import { pageRoutes } from "@/data/routes";
import styles from "../basePage.module.css";
export default function Personal() {
return (
<div className={styles.page}>
<Header />
<SectionHeader title="Personal" subtitle="Life lessons from students" />
<ComponentWrapper heading="What was your favourite extracurricular activity that you participated in during your time at UW?" align="left">
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={P1} circleDiameter={0} height={300} />
</div>
</ComponentWrapper>
<ComponentWrapper heading="What is one extracurricular you regret not joining?" align="left" noBackground>
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={P2} circleDiameter={0} height={300} />
</div>
</ComponentWrapper>
<ComponentWrapper heading="What is the best life hack/tip?" align="right">
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={P3} circleDiameter={0} height={300} />
</div>
</ComponentWrapper>
<ComponentWrapper heading="What is your favourite inspirational quote/words to live by?" align="right" noBackground>
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={P4} circleDiameter={0} height={400} width={700} />
</div>
</ComponentWrapper>
<ComponentWrapper heading="What is your most embarrassing story from your time at UW?" align="left">
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={P5} circleDiameter={0} height={300} />
</div>
</ComponentWrapper>
<ComponentWrapper heading="What is the nicest thing someone at UW did for you?" align="left" noBackground>
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={P6} circleDiameter={0} height={300} />
</div>
</ComponentWrapper>
<ComponentWrapper heading="What is one regret you have after finishing university?" align="right">
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={P7} circleDiameter={0} height={300} />
</div>
</ComponentWrapper>
<ComponentWrapper heading="What is one thing that you wish you could tell your first-year self?" align="right" noBackground>
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={P8} circleDiameter={0} height={300} />
</div>
</ComponentWrapper>
<ComponentWrapper heading="What is the best lesson you learned from your time at UW?" align="left">
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={P9} circleDiameter={0} height={300} />
</div>
</ComponentWrapper>
<ComponentWrapper heading="What is your favourite memory from your time at UW?" align="left" noBackground>
<div className={styles.quotationCarouselContainer}>
<QuotationCarousel data={P10} circleDiameter={0} height={400} width={400} />
</div>
</ComponentWrapper>
<BottomNav leftPage={pageRoutes.mentalHealth} rightPage={pageRoutes.contributors} />
</div>
);
}

7
app/post-grad/layout.tsx Normal file
View File

@ -0,0 +1,7 @@
import { title } from "@/utils/title";
import React, { PropsWithChildren } from "react";
export const metadata = title("Post-grad");
const Layout: React.FC<PropsWithChildren> = ({ children }) => children;
export default Layout;

86
app/post-grad/page.tsx Normal file
View File

@ -0,0 +1,86 @@
"use client";
import { BarGraphHorizontal } from "@/components/BarGraph";
import { BottomNav } from "@/components/BottomNav";
import { ComponentWrapper } from "@/components/ComponentWrapper";
import { Header } from "@/components/Header";
import { PieChart } from "@/components/PieChart";
import { SectionHeader } from "@/components/SectionHeader";
import { P1, P2, P3, P4 } from "@/data/post-grad";
import { pageRoutes } from "@/data/routes";
import { barGraphMargin, barGraphProps, pieChartProps } from "@/utils/defaultProps";
import { useWindowDimensions } from "@/utils/getWindowDimensions";
import { useIsMobile } from "@/utils/isMobile";
import styles from "../basePage.module.css";
export default function PostGrad() {
const pageWidth = useWindowDimensions().width;
const isMobile = useIsMobile();
return (
<div className={styles.page}>
<Header />
<SectionHeader title="Post-grad" subtitle="Furthering your Computer Science Academic Journey" />
<ComponentWrapper
heading="Do you plan on pursuing post-graduate education?"
bodyText={
<p>
Out of the 133 respondents in this section, about 50% of them are not planning on pursuing a post-graduate education, while 13% are planning to do
so and 29% are currently unsure. Post-graduate education is an option, but does not have to be everyone&apos;s pathway!
</p>
}
align="left">
<div className={styles.graphContainer}>
<BarGraphHorizontal data={P1} {...barGraphProps(isMobile, pageWidth, true)} margin={{ ...barGraphMargin, left: 150 }} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="What proportion of friends will you keep in contact with post-graduation?"
bodyText={
<p>
At university, people often make many long-lasting friendships and connections! All of the respondents will be keeping at least some friends, with
the vast majority being some, half, or most of their current friends, and a small percentage keeping all of their friends.
</p>
}
align="right"
noBackground>
<div className={styles.graphContainer}>
<PieChart data={P2} {...pieChartProps(isMobile, pageWidth)} />
</div>
</ComponentWrapper>
<ComponentWrapper
heading="If you searched for a job, how many onsites/interviews did you get?"
bodyText={
<p>
56 participants reported having at least one interview, with most having up to five, but a few had as many as 80. Some did not interview at all,
which may be a result of taking a return offer from a previous co-op placement.
</p>
}
align="left">
<div className="center-col">
<PieChart data={P3} {...pieChartProps(isMobile, pageWidth, true)} />
<span>mean: 7.911 | min: 1 | Q1: 2 | median: 5 | Q3: 9 | max: 80</span>
</div>
</ComponentWrapper>
<ComponentWrapper
heading="Have you secured a full-time position post-grad?"
bodyText={
<p>
Most students have secured a full-time position post-grad, at 71% of respondents. Some of these positions could be return offers, while some
students may have found new positions. Either way, the two years of co-op experience seem to have paid off in securing these students a job position
post-grad!
</p>
}
align="right"
noBackground>
<PieChart data={P4} {...pieChartProps(isMobile, pageWidth)} />
</ComponentWrapper>
<BottomNav leftPage={pageRoutes.intimacyAndDrugs} rightPage={pageRoutes.fullTime} />
</div>
);
}

7
app/sandbox/layout.tsx Normal file
View File

@ -0,0 +1,7 @@
import { title } from "@/utils/title";
import React, { PropsWithChildren } from "react";
export const metadata = title("Sandbox");
const Layout: React.FC<PropsWithChildren> = ({ children }) => children;
export default Layout;

13
app/sandbox/page.tsx Normal file
View File

@ -0,0 +1,13 @@
import Image from "next/image";
export default function Sandbox() {
return (
<>
<Image src="/images/goose1.svg" alt="Goose #1" width={200} height={200} />
<Image src="/images/goose2.svg" alt="Goose #2" width={200} height={200} />
<Image src="/images/goose3.svg" alt="Goose #3" width={200} height={200} />
<Image src="/images/grades.svg" alt="Grades" width={200} height={200} />
<Image src="/images/laptop.svg" alt="Laptop" width={200} height={200} />
</>
);
}

View File

@ -0,0 +1,72 @@
.aboutWrapper {
position: relative;
width: 90%;
scroll-margin-top: 50px;
}
.about {
display: flex;
flex-direction: row;
padding: calc(45rem / 16);
}
.about h1 {
margin: 0;
}
.about h4 {
margin: 0;
}
.about aside {
flex: 1;
justify-content: space-between;
margin-right: calc(40rem / 18);
}
.about aside h1 {
color: var(--primary-pink);
margin-bottom: calc(40rem / 10);
}
.about aside h4 {
color: var(--primary-text);
}
.about article {
flex: 3;
}
.about article h4 {
color: var(--primary-yellow);
}
.about article p {
color: var(--primary-text);
}
.angle {
position: absolute;
top: 0;
left: 0;
width: calc(70rem / 16);
height: calc(70rem / 16);
}
.anglePath {
stroke: var(--primary-text);
}
.left.angle {
transform: rotate(180deg);
top: unset;
left: unset;
bottom: 0;
right: 0;
}
@media screen and (max-width: 900px) {
.about {
flex-direction: column;
}
}

50
components/About.tsx Normal file
View File

@ -0,0 +1,50 @@
import React from "react";
import styles from "./About.module.css";
export function About() {
return (
<div className={styles.aboutWrapper} id="about">
<AngleDecoration isBottom={false} />
<section className={styles.about}>
<aside>
<h1>About the Programs</h1>
<h4>Getting an overview of the CS programs in UW</h4>
</aside>
<article>
<h4>Computer Science</h4>
<p>
Computer Science (CS) is commonly offered by the Faculty of Mathematics as a co-op program, with students usually attending 8 school and 6 co-op
terms in their degree. However, CS is more flexible than the other two programs because of the ability to choose from a wider range and number of
electives, to take terms off, and to change their academic schedules to fit their needs.
</p>
<h4>Computing and Financial Management</h4>
<p>
Computing and Financial Management (CFM) combines the core CS courses with electives from areas such as accounting, economics, and financial
management. This is a joint offering by the Faculty of Mathematics and the School of Accounting and Finance. The program is offered only as a co-op
program with 6 co-op terms.{" "}
</p>
<h4>Computer Science/Business Administration</h4>
<p>
Joint with Wilfrid Laurier University, the Business Administration and Computer Science Double Degree (CS/BBA) is an exclusive offering that allows
students to gain experience in CS as well as many subfields of business. There are 10 school terms and either 4 or 5 co-op terms in the usual
schedule, so it&apos;s a longer degree with more academic terms than CS or CFM.
</p>
</article>
</section>
<AngleDecoration isBottom />
</div>
);
}
interface AngleDecorationProps {
isBottom: boolean;
}
function AngleDecoration({ isBottom }: AngleDecorationProps) {
return (
<svg viewBox="0 0 100 100" className={isBottom ? `${styles.left} ${styles.angle}` : styles.angle}>
<path d="M100,2 L2,2 L2,100" fill="none" strokeWidth="10" className={styles.anglePath} />
</svg>
);
}

View File

@ -0,0 +1,53 @@
.barBackground {
fill: var(--card-background);
transition: fill 0.5s ease-out;
}
.blue {
--fill: var(--chart-blue-light);
--hover-fill: var(--chart-blue-heavy);
--hover-shadow: var(--chart-blue-light);
}
.yellow {
--fill: var(--chart-yellow-light);
--hover-fill: var(--chart-yellow-heavy);
--hover-shadow: var(--chart-yellow-light);
}
.green {
--fill: var(--chart-green-light);
--hover-fill: var(--chart-green-heavy);
--hover-shadow: var(--chart-green-light);
}
.pink {
--fill: var(--chart-pink-light);
--hover-fill: var(--chart-pink-heavy);
}
.bar {
fill: var(--fill);
transition: fill 0.5s ease-out;
}
.barGroup {
transition: fill 0.5s ease-out;
}
.barGroup:hover .bar {
fill: var(--hover-fill);
filter: drop-shadow(0 0 calc(4rem / 16) var(--hover-shadow));
}
.tickLabel {
font-family: "Lexend", sans-serif;
font-weight: 800;
fill: var(--label);
}
.axisLabel {
font-family: "Lexend", sans-serif;
font-weight: 800;
fill: var(--label);
}

374
components/BarGraph.tsx Normal file
View File

@ -0,0 +1,374 @@
import { Color } from "@/utils/Color";
import { AxisBottom, AxisLeft } from "@visx/axis";
import { bottomTickLabelProps } from "@visx/axis/lib/axis/AxisBottom";
import { leftTickLabelProps } from "@visx/axis/lib/axis/AxisLeft";
import { GridColumns, GridRows } from "@visx/grid";
import { Group } from "@visx/group";
import { scaleBand, scaleLinear } from "@visx/scale";
import { Bar } from "@visx/shape";
import { withTooltip } from "@visx/tooltip";
import { getTooltipPosition, TooltipWrapper } from "./TooltipWrapper";
import styles from "./BarGraph.module.css";
interface BarGraphProps {
data: BarGraphData[];
/** Width of the entire graph, in pixels. */
width: number;
/** Height of the entire graph, in pixels. */
height: number;
/** Distance between the edge of the graph and the area where the bars are drawn, in pixels. */
margin: {
top: number;
bottom: number;
left: number;
right: number;
};
className?: string;
/** Font size of the category axis tick labels, in pixels. Default is 16px. */
categoryTickLabelSize?: number;
/** Font size of the value axis tick labels, in pixels. Default is 16px. */
valueTickLabelSize?: number;
/** Label text for the category axis. */
categoryAxisLabel?: string;
/** Font size of the label for the cateogry axis, in pixels. */
categoryAxisLabelSize?: number;
/** Controls the distance between the category axis label and the category axis. */
categoryAxisLabelOffset?: number;
/** Label text for the value axis. */
valueAxisLabel?: string;
/** Font size of the label for the value axis, in pixels. */
valueAxisLabelSize?: number;
/** Controls the distance between the value axis label and the value axis. */
valueAxisLabelOffset?: number;
/** Minimum width of the graph. */
minWidth?: number;
/** Breakpoint width of graph where alernating labels are displayed. Only for Vertical graphs */
widthAlternatingLabel?: number;
/** Space added to the bottom of the graph to show overflowing labels. Only for Vertical graphs */
alternatingLabelSpace?: number;
/** Default position of labels in x-axis, in px. */
defaultLabelDy?: string;
/** Position of lower labels in x-axis, in px. Only for Vertical graphs */
lowerLabelDy?: string;
/** The color of the bars */
color?: "blue" | "yellow" | "green" | "pink";
background?: boolean;
}
interface BarGraphData {
category: string;
value: number;
}
const DEFAULT_LABEL_SIZE = 16;
type TooltipData = string;
export const BarGraphHorizontal = withTooltip<BarGraphProps, TooltipData>(
({
width,
height,
margin,
data,
className,
minWidth = 500,
categoryTickLabelSize = DEFAULT_LABEL_SIZE,
valueTickLabelSize = DEFAULT_LABEL_SIZE,
categoryAxisLabel,
categoryAxisLabelSize = DEFAULT_LABEL_SIZE,
categoryAxisLabelOffset = 0,
valueAxisLabel,
valueAxisLabelSize = DEFAULT_LABEL_SIZE,
valueAxisLabelOffset = 0,
defaultLabelDy = "0",
tooltipOpen,
tooltipLeft,
tooltipTop,
tooltipData,
hideTooltip,
showTooltip,
background = false,
color = background ? "blue" : "pink", // In Block : Blue, Elsewise : Pink
}) => {
width = width < minWidth ? minWidth : width; // Ensuring graph's width >= minWidth
const barPadding = 0.4;
const categoryMax = height - margin.top - margin.bottom;
const valueMax = width - margin.left - margin.right;
const getCategory = (d: BarGraphData) => d.category;
const getValue = (d: BarGraphData) => d.value;
const categoryScale = scaleBand({
range: [0, categoryMax],
domain: data.map(getCategory),
padding: barPadding,
});
const valueScale = scaleLinear({
range: [0, valueMax],
nice: true,
domain: [0, Math.max(...data.map(getValue))],
});
const categoryPoint = (d: BarGraphData) => categoryScale(getCategory(d));
const valuePoint = (d: BarGraphData) => valueScale(getValue(d));
return (
<div>
<svg className={className} width={width} height={height}>
<Group top={margin.top} left={margin.left}>
<Group>
{data.map((d, idx) => {
const barName = `${getCategory(d)}-${idx}`;
const barWidth = categoryScale.bandwidth();
const backgroundBarWidth = barWidth / (1 - barPadding);
return idx % 2 === 0 ? (
<Bar
className={styles.barBackground}
key={`bar-${barName}-background`}
x={0}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
y={categoryPoint(d)! - (backgroundBarWidth - barWidth) / 2}
width={valueMax}
height={backgroundBarWidth}
/>
) : null;
})}
</Group>
<GridColumns scale={valueScale} height={categoryMax} numTicks={5} stroke={Color.label} strokeWidth={4} strokeDasharray="10" strokeLinecap="round" />
<Group>
{data.map((d, idx) => {
const barName = `${getCategory(d)}-${idx}`;
const barLength = valuePoint(d);
const barWidth = categoryScale.bandwidth();
return (
<Group className={styles.barGroup} key={`bar-${barName}`}>
<Bar
onMouseMove={(e) => {
const tooltipPos = getTooltipPosition(e);
showTooltip({
tooltipData: getValue(d).toString(),
tooltipLeft: tooltipPos.x,
tooltipTop: tooltipPos.y,
});
}}
onMouseOut={hideTooltip}
className={`${styles.bar} ${styles[color]}`}
x={0}
y={categoryPoint(d)}
width={barLength}
height={barWidth}
/>
</Group>
);
})}
</Group>
<AxisLeft
scale={categoryScale}
hideAxisLine
hideTicks
tickLabelProps={() => {
return {
...leftTickLabelProps,
className: styles.tickLabel,
fontSize: `${categoryTickLabelSize / 16}rem`,
};
}}
label={categoryAxisLabel}
labelClassName={styles.axisLabel}
labelOffset={categoryAxisLabelOffset}
labelProps={{
fontSize: `${categoryAxisLabelSize / 16}rem`,
}}
/>
<AxisBottom
scale={valueScale}
top={categoryMax}
hideAxisLine
hideTicks
numTicks={5}
tickLabelProps={() => {
return {
...bottomTickLabelProps,
className: styles.tickLabel,
dy: defaultLabelDy,
fontSize: `${valueTickLabelSize / 16}rem`,
};
}}
label={valueAxisLabel}
labelClassName={styles.axisLabel}
labelOffset={valueAxisLabelOffset}
labelProps={{
fontSize: `${valueAxisLabelSize / 16}rem`,
}}
/>
</Group>
</svg>
{tooltipOpen && <TooltipWrapper top={tooltipTop} left={tooltipLeft} header={tooltipData as string}></TooltipWrapper>}
</div>
);
},
);
export const BarGraphVertical = withTooltip<BarGraphProps, TooltipData>(
({
width,
height,
margin,
data,
className,
minWidth = 500,
categoryTickLabelSize = DEFAULT_LABEL_SIZE,
valueTickLabelSize = DEFAULT_LABEL_SIZE,
categoryAxisLabel,
categoryAxisLabelSize = DEFAULT_LABEL_SIZE,
categoryAxisLabelOffset = 0,
valueAxisLabel,
valueAxisLabelSize = DEFAULT_LABEL_SIZE,
valueAxisLabelOffset = 0,
widthAlternatingLabel = 600,
alternatingLabelSpace = 80,
defaultLabelDy = `0px`,
lowerLabelDy = `30px`,
tooltipOpen,
tooltipLeft,
tooltipTop,
tooltipData,
hideTooltip,
showTooltip,
background = false,
color = background ? "blue" : "pink",
}) => {
width = width < minWidth ? minWidth : width; // Ensuring graph's width >= minWidth
const barPadding = 0.4;
const alternatingLabel = width <= widthAlternatingLabel;
const final_margin_bottom = alternatingLabel ? margin.bottom + alternatingLabelSpace : margin.bottom;
const categoryMax = width - margin.left - margin.right;
const valueMax = height - margin.top - final_margin_bottom;
const getCategory = (d: BarGraphData) => d.category;
const getValue = (d: BarGraphData) => d.value;
const categoryScale = scaleBand({
range: [0, categoryMax],
domain: data.map(getCategory),
padding: barPadding,
});
const valueScale = scaleLinear({
range: [valueMax, 0],
nice: true,
domain: [0, Math.max(...data.map(getValue))],
});
const categoryPoint = (d: BarGraphData) => categoryScale(getCategory(d));
const valuePoint = (d: BarGraphData) => valueScale(getValue(d));
return (
<div>
<svg className={className} width={width} height={height}>
<Group top={margin.top} left={margin.left}>
<Group>
{data.map((d, idx) => {
const barName = `${getCategory(d)}-${idx}`;
const barWidth = categoryScale.bandwidth();
const backgroundBarWidth = barWidth / (1 - barPadding);
return idx % 2 === 0 ? (
<Bar
className={styles.barBackground}
key={`bar-${barName}-background`}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
x={categoryPoint(d)! - (backgroundBarWidth - barWidth) / 2}
y={0}
width={backgroundBarWidth}
height={valueMax}
/>
) : null;
})}
</Group>
<GridRows scale={valueScale} width={categoryMax} numTicks={5} stroke={Color.label} strokeWidth={4} strokeDasharray="10" strokeLinecap="round" />
<Group>
{data.map((d, idx) => {
const barName = `${getCategory(d)}-${idx}`;
const barHeight = valueMax - valuePoint(d);
const barWidth = categoryScale.bandwidth();
return (
<Group className={styles.barGroup} key={`bar-${barName}`}>
<Bar
onMouseMove={(e) => {
const tooltipPos = getTooltipPosition(e);
showTooltip({
tooltipData: getValue(d).toString(),
tooltipLeft: tooltipPos.x,
tooltipTop: tooltipPos.y,
});
}}
onMouseOut={hideTooltip}
className={`${styles.bar} ${styles[color]}`}
x={categoryPoint(d)}
y={valueMax - barHeight}
width={barWidth}
height={barHeight}
/>
</Group>
);
})}
</Group>
<AxisBottom
scale={categoryScale}
top={valueMax}
hideAxisLine
hideTicks
tickLabelProps={(value, index) => {
const alternatingDy = index % 2 == 0 ? defaultLabelDy : lowerLabelDy;
return {
...bottomTickLabelProps,
className: styles.tickLabel,
dy: alternatingLabel ? alternatingDy : defaultLabelDy,
fontSize: `${categoryTickLabelSize / 16}rem`,
width: categoryScale.bandwidth(),
verticalAnchor: "start",
};
}}
label={categoryAxisLabel}
labelClassName={styles.axisLabel}
labelOffset={categoryAxisLabelOffset}
labelProps={{
fontSize: `${categoryAxisLabelSize / 16}rem`,
}}
/>
<AxisLeft
scale={valueScale}
hideAxisLine
hideTicks
numTicks={5}
tickLabelProps={() => {
return {
...leftTickLabelProps,
className: styles.tickLabel,
dx: "-0.5rem",
dy: "0.25rem",
fontSize: `${valueTickLabelSize / 16}rem`,
};
}}
label={valueAxisLabel}
labelClassName={styles.axisLabel}
labelOffset={valueAxisLabelOffset}
labelProps={{
fontSize: `${valueAxisLabelSize / 16}rem`,
}}
/>
</Group>
</svg>
{tooltipOpen && <TooltipWrapper top={tooltipTop} left={tooltipLeft} header={tooltipData as string}></TooltipWrapper>}
</div>
);
},
);

7
components/BlankLink.tsx Normal file
View File

@ -0,0 +1,7 @@
import React from "react";
export const BodyLink = ({ targetBlank = true, children, href }: { href: string; targetBlank?: boolean; children: React.ReactNode }) => (
<a href={href} target={targetBlank ? "_blank" : ""} rel="noreferrer">
<b>{children}</b>
</a>
);

View File

@ -0,0 +1,108 @@
.container {
display: flex;
flex-flow: center;
align-items: center;
justify-content: space-between;
margin: calc(40rem / 16) 0;
}
.subBox {
display: inline-block;
}
.leftItem {
text-align: right;
}
.item {
color: var(--primary-text);
font-size: calc(28rem / 16);
position: relative;
margin: calc(24rem / 16);
}
.subBox {
display: flex;
flex-direction: row;
align-items: center;
}
.arrow {
width: calc(250rem / 16);
height: calc(20rem / 16);
display: flex;
align-items: center;
justify-content: center;
}
.item:after {
content: "";
position: absolute;
width: 100%;
transform: scaleX(0);
height: calc(2rem / 16);
bottom: 0;
left: 0;
background-color: var(--primary-accent);
cursor: pointer;
transform-origin: bottom right;
transition: transform 0.25s ease-out;
}
.item:hover:after {
transform: scaleX(1);
transform-origin: bottom left;
}
.linePath {
stroke: var(--primary-text);
}
.arrowPath {
fill: var(--primary-text);
}
.right {
transform: rotate(180deg);
}
@media screen and (max-width: 1000px) {
.subBox {
flex-direction: column;
align-items: flex-start;
}
.subBoxLeft {
flex-direction: column-reverse;
align-items: flex-end;
}
.item {
font-size: calc(20rem / 16);
margin: 0;
margin-bottom: calc(10rem / 16);
}
.arrow {
width: calc(200rem / 16);
}
}
@media screen and (max-width: 500px) {
.container {
justify-content: center;
gap: calc(50rem / 16);
}
.arrow {
width: 100%;
}
}
.containerOnlyRightArrow {
justify-content: flex-end;
}
.containerOnlyLeftArrow {
justify-content: flex-start;
}

72
components/BottomNav.tsx Normal file
View File

@ -0,0 +1,72 @@
import Link from "next/link";
import styles from "./BottomNav.module.css";
interface PagesInfo {
leftPage?: {
url: string;
name: string;
};
rightPage?: {
url: string;
name: string;
};
}
export function BottomNav(props: PagesInfo) {
const onlyRightArrow = props.rightPage && !props.leftPage;
const onlyLeftArrow = !props.rightPage && props.leftPage;
return (
<div
className={`${styles.container}
${onlyRightArrow ? styles.containerOnlyRightArrow : ""}
${onlyLeftArrow ? styles.containerOnlyLeftArrow : ""}`}>
{props.leftPage ? (
<div className={styles.subBox + " " + styles.subBoxLeft}>
<Link href={props.leftPage.url} scroll>
<Arrow />
</Link>
<Link href={props.leftPage.url} scroll className={styles.item + " " + styles.leftItem}>
{props.leftPage.name}
</Link>
</div>
) : null}
{props.rightPage ? (
<div className={styles.subBox}>
<Link href={props.rightPage.url} scroll className={styles.item}>
{props.rightPage.name}
</Link>
<Link href={props.rightPage.url} scroll>
<Arrow isPointingRight />
</Link>
</div>
) : null}
</div>
);
}
interface ArrowProps {
isPointingRight?: boolean;
}
function Arrow({ isPointingRight }: ArrowProps) {
return (
<svg className={(isPointingRight ? styles.right : "") + " " + styles.arrow}>
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="5" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,6 L9,3 z" className={styles.arrowPath} />
</marker>
</defs>
<line
x1="250"
y1="10"
x2="100"
y2="10" // half of svg height
strokeWidth="3"
markerEnd="url(#arrow)"
className={styles.linePath}
/>
</svg>
);
}

View File

@ -0,0 +1,19 @@
.blueboxplot {
fill: var(--chart-blue-light);
transition: fill 0.5s ease-out;
}
.blueboxplot:hover {
fill: var(--chart-blue-heavy);
filter: drop-shadow(0 0 calc(4rem / 16) var(--primary-accent));
}
.pinkboxplot {
fill: var(--primary-accent-light);
transition: fill 0.5s ease-out;
}
.pinkboxplot:hover {
fill: var(--primary-accent);
filter: drop-shadow(0 0 calc(4rem / 16) var(--primary-accent));
}

305
components/Boxplot.tsx Normal file
View File

@ -0,0 +1,305 @@
import { Color } from "@/utils/Color";
import { AxisBottom, AxisLeft } from "@visx/axis";
import { GridColumns, GridRows } from "@visx/grid";
import { Group } from "@visx/group";
import { Stats } from "@visx/mock-data/lib/generators/genStats";
import { Point } from "@visx/point";
import { scaleBand, scaleLinear } from "@visx/scale";
import { Line } from "@visx/shape";
import { BoxPlot as VisxBoxPlot } from "@visx/stats";
import { withTooltip } from "@visx/tooltip";
import { WithTooltipProvidedProps } from "@visx/tooltip/lib/enhancers/withTooltip";
import React from "react";
import { getTooltipPosition, TooltipWrapper } from "./TooltipWrapper";
import styles from "./Boxplot.module.css";
const DEFAULT_LABEL_SIZE = 16;
const TICK_LABEL_FONT_WEIGHT = 800;
interface BoxPlotData {
category: string;
min: number;
median: number;
max: number;
firstQuartile: number;
thirdQuartile: number;
outliers?: number[];
}
type TooltipData = Omit<BoxPlotData, "outliers">;
export type StatsPlotProps = {
data: BoxPlotData[];
/** Width of the entire graph, in pixels, greater than 10. */
width: number;
/** Height of the entire graph, in pixels. */
height: number;
/** Distance between the edge of the graph and the area where the bars are drawn, in pixels. */
margin: {
top: number;
left: number;
};
/** Width of the lines in the graph, in px. */
strokeWidth?: number;
/** Length of the dashes and the gaps in the graph, in px. */
strokeDashArray?: string;
/** Number of ticks for the value (y-)axis */
numTicksLeftAxis?: number;
/** Left margin before the start of the graph for the left axis labels, in px. */
valueAxisLeftMargin?: number;
/** Distance between the left axis labels and the start of the graph */
valueAxisLabelOffset?: number;
/** Distance between the top and the column lines of the grid of the graph, in px. */
gridColumnTopOffset?: number;
/** Distance between the top of the point in the boxplot and the start of the tooltip box, in px. */
toolTipTopOffset?: number;
/** Distance between the left of the point in the boxplot and the start of the tooltip box, in px. */
toolTipLeftOffset?: number;
/** Font size of the category (x-)axis labels */
categoryAxisLabelSize?: number;
/** Font size of the value (y-)axis labels */
valueAxisLabelSize?: number;
/** Font size of the text in the tool tip box */
toolTipFontSize?: number;
/** Factor multiplied with the compressed width to determine the box width, in px. */
boxPlotWidthFactor?: number;
/** Factor multiplied with the compressed width to determine the distance between boxes, in px. */
boxPlotLeftOffset?: number;
/** Boxplot padding */
boxPlotPadding?: number;
/** Minimum width of the graph. */
minWidth?: number;
background?: boolean;
};
export const BoxPlot = withTooltip<StatsPlotProps, TooltipData>(
({
width,
height,
data,
margin,
tooltipOpen,
tooltipLeft,
tooltipTop,
tooltipData,
showTooltip,
hideTooltip,
strokeWidth = 2.5,
strokeDashArray = "10,4",
numTicksLeftAxis = 6,
valueAxisLeftMargin = 40,
gridColumnTopOffset = -20,
valueAxisLabelOffset = -10,
toolTipTopOffset = 0,
toolTipLeftOffset = 0,
categoryAxisLabelSize = DEFAULT_LABEL_SIZE,
valueAxisLabelSize = DEFAULT_LABEL_SIZE,
boxPlotWidthFactor = 0.4,
boxPlotLeftOffset = 0.3,
boxPlotPadding = 0.3,
minWidth = 500,
background = false,
}: StatsPlotProps & WithTooltipProvidedProps<TooltipData>) => {
if (width < minWidth) {
width = minWidth;
}
// bounds
const xMax = width;
const yMax = height - 120;
// formatting data
const plotData: Stats[] = data.map((d) => {
return {
boxPlot: {
...d,
x: d.category,
outliers: [],
},
binData: [],
};
});
// accessors
const getX = (d: Stats) => d.boxPlot.x;
const getMin = (d: Stats) => d.boxPlot.min;
const getMax = (d: Stats) => d.boxPlot.max;
const getMedian = (d: Stats) => d.boxPlot.median;
const getFirstQuartile = (d: Stats) => d.boxPlot.firstQuartile;
const getThirdQuartile = (d: Stats) => d.boxPlot.thirdQuartile;
// scales
const xScale = scaleBand<string>({
range: [margin.left, xMax - 2 * margin.left - valueAxisLeftMargin], // scaling is needed due to left margin
round: true,
domain: plotData.map(getX),
padding: boxPlotPadding,
});
const values = plotData.reduce((allValues, { boxPlot }) => {
allValues.push(boxPlot.min, boxPlot.max);
return allValues;
}, [] as number[]);
const maxYValue = Math.max(...values);
const yScale = scaleLinear<number>({
range: [yMax - margin.top, 0],
round: true,
domain: [0, maxYValue],
});
const constrainedWidth = Math.min(200, xScale.bandwidth());
const mouseOverEventHandler = (d: Stats) => (e: React.MouseEvent<SVGLineElement | SVGRectElement, MouseEvent>) => {
const pos = getTooltipPosition(e);
showTooltip({
tooltipLeft: pos.x + toolTipLeftOffset,
tooltipTop: pos.y + toolTipTopOffset,
tooltipData: {
...d.boxPlot,
category: getX(d),
},
});
};
return width < 10 ? null : (
<div>
<svg width={width} height={height}>
<Group top={margin.top} left={margin.left}>
<Group left={valueAxisLeftMargin}>
<GridRows
scale={yScale}
width={xMax}
numTicks={numTicksLeftAxis}
stroke={Color.tertiaryBackground}
strokeWidth={strokeWidth}
strokeDasharray={strokeDashArray}
/>
<GridColumns
scale={xScale}
height={yMax - gridColumnTopOffset}
top={gridColumnTopOffset}
stroke={Color.tertiaryBackground}
strokeWidth={strokeWidth}
strokeDasharray={strokeDashArray}
/>
<AxisBottom
top={yMax - gridColumnTopOffset}
scale={xScale}
hideAxisLine
hideTicks
labelProps={{
fontSize: `${categoryAxisLabelSize / 16}rem`,
}}
tickLabelProps={() => {
return {
fill: Color.label,
fontWeight: TICK_LABEL_FONT_WEIGHT,
textAnchor: "middle",
};
}}
/>
<AxisLeft
scale={yScale}
left={valueAxisLabelOffset}
numTicks={numTicksLeftAxis}
hideAxisLine
labelProps={{
fontSize: `${valueAxisLabelSize / 16}rem`,
}}
tickLabelProps={() => {
return {
fill: Color.label,
fontWeight: TICK_LABEL_FONT_WEIGHT,
textAnchor: "end",
verticalAnchor: "middle",
};
}}
/>
<Line
fill={Color.tertiaryBackground}
to={new Point({ x: 0, y: gridColumnTopOffset })}
from={new Point({ x: 0, y: yMax })}
stroke={Color.tertiaryBackground}
strokeWidth={strokeWidth}
strokeDasharray={strokeDashArray}
/>
</Group>
<Line
fill={Color.tertiaryBackground}
to={
new Point({
x: xMax - margin.left - strokeWidth,
y: gridColumnTopOffset,
})
}
from={
new Point({
x: xMax - margin.left - strokeWidth,
y: yMax,
})
}
stroke={Color.tertiaryBackground}
strokeWidth={strokeWidth}
strokeDasharray={strokeDashArray}
/>
{plotData.map((d: Stats, i) => (
<Group key={i}>
<VisxBoxPlot
className={background ? styles.blueboxplot : styles.pinkboxplot}
min={getMin(d)}
max={getMax(d)}
left={xScale(getX(d))! + boxPlotLeftOffset * constrainedWidth + valueAxisLeftMargin}
firstQuartile={getFirstQuartile(d)}
thirdQuartile={getThirdQuartile(d)}
median={getMedian(d)}
boxWidth={constrainedWidth * boxPlotWidthFactor}
rx={0}
ry={0}
stroke={Color.label}
strokeWidth={strokeWidth}
valueScale={yScale}
minProps={{
onMouseMove: mouseOverEventHandler(d),
onMouseLeave: hideTooltip,
}}
maxProps={{
onMouseMove: mouseOverEventHandler(d),
onMouseLeave: hideTooltip,
}}
boxProps={{
onMouseMove: mouseOverEventHandler(d),
strokeWidth: 0,
onMouseLeave: hideTooltip,
}}
medianProps={{
style: {
stroke: Color.label,
},
onMouseMove: mouseOverEventHandler(d),
onMouseLeave: () => {
hideTooltip();
},
}}
/>
</Group>
))}
</Group>
</svg>
{tooltipOpen && tooltipData && (
<TooltipWrapper left={tooltipLeft} top={tooltipTop} header={tooltipData.category}>
<p>max: {tooltipData.max}</p>
<p>third quartile: {tooltipData.thirdQuartile}</p>
<p>median: {tooltipData.median}</p>
<p>first quartile: {tooltipData.firstQuartile}</p>
<p>min: {tooltipData.min}</p>
</TooltipWrapper>
)}
</div>
);
},
);

View File

@ -0,0 +1,21 @@
.box {
width: calc(100rem / 16);
height: calc(100rem / 16);
margin-bottom: calc(10rem / 16);
}
.wrapper {
display: flex;
flex-direction: row;
justify-content: space-around;
flex-wrap: wrap;
}
.item {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
margin: calc(10rem / 16) calc(60rem / 16);
width: calc(150rem / 16);
}

View File

@ -0,0 +1,20 @@
import React from "react";
import { Color } from "@/utils/Color";
import styles from "./ColorPalette.module.css";
export function ColorPalette() {
return (
<>
<h2>Color Palette</h2>
<div className={styles.wrapper}>
{Object.entries(Color).map(([colorName, colorCSSName]) => (
<div key={colorName} className={styles.item}>
<div className={styles.box} style={{ backgroundColor: colorCSSName }} key={colorName} />
<span>{colorName}</span>
</div>
))}
</div>
</>
);
}

View File

@ -0,0 +1,63 @@
.btn {
--button-color: var(--primary-accent-darker);
--border-color: var(--link);
--selected-button-color: var(--primary-accent-dark);
--selected-button-border-color: var(--link-hover);
--hover-button-color: var(--primary-accent-dark);
--hover-button-border-color: var(--link-hover);
display: inline-block;
height: calc(60rem / 16);
line-height: calc(30rem / 16);
background-color: var(--button-color);
padding: 0 calc(30rem / 16);
border-radius: 99em;
text-decoration: none;
color: #fff;
font-size: calc(18rem / 16);
vertical-align: bottom;
white-space: nowrap;
border: calc(3rem / 16) solid var(--border-color);
font-family: "Lexend", sans-serif;
transition:
0.15s background-color,
0.15s border-color,
0.15s color,
0.15s fill;
font-weight: 600;
cursor: pointer;
margin: calc(8rem / 16) calc(3rem / 16);
text-align: center;
}
.btn:hover {
--button-color: var(--hover-button-color);
--border-color: var(--hover-button-border-color);
background-color: var(--button-color);
border: calc(3rem / 16) solid var(--border-color);
}
.btnContainer {
display: block;
text-align: center;
margin: auto;
}
.selectedBtn {
--button-color: var(--selected-button-color);
--border-color: var(--selected-button-border-color);
background-color: var(--button-color);
border: calc(3rem / 16) solid var(--border-color);
}
.selectedBtn:hover {
--button-color: var(--hover-button-color);
--border-color: var(--hover-button-border-color);
background-color: var(--button-color);
border: calc(3rem / 16) solid var(--border-color);
}

View File

@ -0,0 +1,40 @@
import React, { useState, useEffect } from "react";
import styles from "./ComponentSwitcher.module.css";
type ComponentSwitcherProps = {
buttonList: string[];
graphList: React.ReactNode[];
};
export function ComponentSwitcher({ buttonList, graphList }: ComponentSwitcherProps) {
const [selectedButton, setSelectedButton] = useState(buttonList[0]);
const [currentGraph, setCurrentGraph] = useState(graphList[0]);
const [currentGraphNumber, setCurrentGraphNumber] = useState(0);
const handleSwitch = (buttonName: string) => {
const graphIndex = buttonList.indexOf(buttonName);
setSelectedButton(buttonName);
setCurrentGraph(graphList[graphIndex]);
setCurrentGraphNumber(graphIndex);
};
useEffect(() => {
setCurrentGraph(graphList[currentGraphNumber]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [graphList]);
return (
<div>
<div>{currentGraph}</div>
<div className={styles.btnContainer}>
{buttonList.map((buttonName, idx) => (
// we may also apply style if currently selected button === buttonName
<button key={idx} className={`${styles.btn} ${selectedButton === buttonName ? styles.selectedBtn : ""}`} onClick={() => handleSwitch(buttonName)}>
{buttonName}
</button>
))}
</div>
</div>
);
}

View File

@ -0,0 +1,162 @@
.sideWrapperCommon {
background-color: var(--side-panel);
display: flex;
padding: calc(40rem / 16) calc(50rem / 16);
margin: calc(65rem / 16) 0;
width: 88%;
}
.wrapperRight {
composes: sideWrapperCommon;
align-self: end;
margin-right: 0;
border-radius: calc(200rem / 16) 0 0 calc(200rem / 16);
flex-direction: row-reverse;
padding-right: calc(50rem / 16);
}
.wrapperLeft {
composes: sideWrapperCommon;
align-self: start;
margin-left: 0;
border-radius: 0 calc(200rem / 16) calc(200rem / 16) 0;
flex-direction: row;
padding-left: calc(50rem / 16);
}
.noBackground {
background: none;
align-self: center;
}
.wrapperCenter {
composes: sideWrapperCommon;
flex-direction: column;
text-align: center;
gap: calc(25rem / 16);
/* to match the 65px margin with the left/right variant:
add 45px bottom margin, since internal wrapper contributes 20px for the center component
0px top margin, since h3 contributes 45px and internal wrapper contributes 20px for the center component
*/
margin: 0 0 calc(45rem / 16) 0;
align-self: center;
}
.wrapperCenter .internalWrapper {
margin: auto;
}
.wrapperNoBodyText {
flex-direction: column;
}
.wrapperNoBodyText .internalWrapper {
text-align: center;
}
.withBackground h3 {
font-size: calc(32rem / 16);
font-weight: 700;
color: var(--chart-blue-heavy);
margin-top: calc(24rem / 16);
margin-bottom: calc(16rem / 16);
letter-spacing: 0.075rem;
}
.withBackground a {
color: var(--chart-blue-heavy);
text-decoration: none;
transition: color 0.5s ease-out;
}
.withBackground a:hover {
color: var(--chart-blue-light);
}
.withBackgroundCloud h3 {
font-size: calc(32rem / 16);
font-weight: 700;
color: var(--chart-green-heavy);
margin-top: calc(24rem / 16);
margin-bottom: calc(16rem / 16);
letter-spacing: 0.075rem;
}
.withBackgroundCloud a {
color: var(--chart-green-heavy);
text-decoration: none;
transition: color 0.5s ease-out;
}
.withBackgroundCloud a:hover {
color: var(--chart-green-light);
}
.noBackgroundCloud {
background: none;
align-self: center;
}
.noBackgroundCloud h3 {
font-size: calc(32rem / 16);
font-weight: 700;
color: var(--chart-yellow-heavy);
margin-top: calc(24rem / 16);
margin-bottom: calc(16rem / 16);
letter-spacing: 0.075rem;
}
.noBackgroundCloud a {
color: var(--chart-yellow-heavy);
text-decoration: none;
transition: color 0.5s ease-out;
}
.noBackgroundCloud a:hover {
color: var(--chart-yellow-light);
}
@media screen and (max-width: 900px) {
.sideWrapperCommon {
margin: auto;
flex-direction: column;
text-align: center;
padding: 0;
border-radius: 0;
width: 100%;
}
.wrapperCenter .internalWrapper {
margin: initial;
}
.wrapperCenter {
padding: 0;
}
.horizontalScrollOnMobile {
overflow-x: scroll;
}
.internalWrapper {
/* Without this, some graphs will have an horizontal scroll bar thats not needed */
overflow-x: auto;
}
}
.internalWrapper {
padding: calc(20rem / 16);
}
.internalWrapper p {
font-size: calc(24rem / 16);
opacity: 0.85;
line-height: 1.25;
}
.textWrapper {
/* We add this since we want the text to shrink before the graph ever shrinks */
flex-shrink: 1000;
/* So that text is still readable in the awkward 1000px width screen size */
min-width: 200px;
}

View File

@ -0,0 +1,37 @@
import React from "react";
import styles from "./ComponentWrapper.module.css";
type AlignOption = "left" | "center" | "right";
type ComponentWrapperProps = {
children: React.ReactNode;
heading: string;
bodyText?: React.ReactNode;
align?: AlignOption;
noBackground?: boolean;
wordCloud?: boolean;
};
export function ComponentWrapper({ heading, bodyText, children, align = "left", noBackground = false, wordCloud = false }: ComponentWrapperProps) {
const alignClasses: { [key in AlignOption]: string } = {
left: styles.wrapperLeft,
center: styles.wrapperCenter,
right: styles.wrapperRight,
};
return (
<div
className={`
${alignClasses[align]}
${noBackground ? (wordCloud ? styles.noBackgroundCloud : styles.noBackground) : wordCloud ? styles.withBackgroundCloud : styles.withBackground}
${bodyText ? "" : styles.wrapperNoBodyText}
`}>
<div className={`${styles.internalWrapper} ${styles.textWrapper}`}>
<h3>{heading}</h3>
{bodyText ? typeof bodyText === "string" ? <p>{bodyText}</p> : bodyText : null}
</div>
<div className={`${styles.internalWrapper} ${styles.horizontalScrollOnMobile}`}>{children}</div>
</div>
);
}

View File

@ -0,0 +1,37 @@
.group {
position: absolute;
top: 0;
right: 0;
z-index: -1;
}
.moon {
position: absolute;
top: 0;
right: 0;
}
.goose {
position: absolute;
top: 150px;
right: 175px;
transform: scaleX(-1);
}
@media screen and (max-width: 1600px) {
.group {
scale: 75%;
}
}
@media screen and (max-width: 1200px) {
.group {
scale: 50%;
}
}
@media screen and (max-width: 800px) {
.group {
scale: 32%;
}
}

View File

@ -0,0 +1,11 @@
import Image from "next/image";
import styles from "./GooseAndMoon.module.css";
export function GooseAndMoon() {
return (
<div className={styles.group}>
<Image className={styles.moon} src="/images/big-moon.svg" alt="" width={500} height={500}></Image>
<Image className={styles.goose} src="/images/goose1.svg" alt="" width={320} height={320}></Image>
</div>
);
}

View File

@ -0,0 +1,30 @@
.wrapper {
display: flex;
flex-direction: column;
}
.barBackground {
fill: var(--card-background);
}
.tickLabel {
font-family: "Lexend", sans-serif;
font-weight: 800;
fill: var(--label);
}
.axisLabel {
font-family: "Lexend", sans-serif;
font-weight: 800;
fill: var(--label);
}
.bar {
transition: fill 0.5s ease-out;
}
.legend {
display: flex;
margin: calc(16rem / 16);
justify-content: center;
}

View File

@ -0,0 +1,533 @@
import { Color } from "@/utils/Color";
import { AxisBottom, AxisLeft } from "@visx/axis";
import { bottomTickLabelProps } from "@visx/axis/lib/axis/AxisBottom";
import { leftTickLabelProps } from "@visx/axis/lib/axis/AxisLeft";
import { GridColumns, GridRows } from "@visx/grid";
import { Group } from "@visx/group";
import { LegendOrdinal } from "@visx/legend";
import { scaleBand, scaleLinear, scaleOrdinal } from "@visx/scale";
import { Bar, BarGroup, BarGroupHorizontal } from "@visx/shape";
import { BarGroupBar as BarGroupBarType } from "@visx/shape/lib/types";
import { withTooltip } from "@visx/tooltip";
import React, { useState } from "react";
import { getTooltipPosition, TooltipWrapper } from "./TooltipWrapper";
import styles from "./GroupedBarGraph.module.css";
interface GroupedBarGraphProps {
data: GroupedBarGraphData[];
/** Colours of bars in each group. */
barColors: string[];
/** Object mapping from the possible colours of bars in each group (barColors) to the colour of the bar when hovered. */
barHoverColorsMap: Record<string, string>;
/** Width of the entire graph, in pixels. */
width: number;
/** Height of the entire graph, in pixels. */
height: number;
/** Distance between the edge of the graph and the area where the bars are drawn, in pixels. */
margin: {
top: number;
bottom: number;
left: number;
right: number;
};
className?: string;
/** Font size of the category axis tick labels, in pixels. Default is 16px. */
categoryTickLabelSize?: number;
/** Font size of the value axis tick labels, in pixels. Default is 16px. */
valueTickLabelSize?: number;
/** Font size of the value that appears when hovering over a bar, in pixels. */
hoverLabelSize?: number;
/** Label text for the category axis. */
categoryAxisLabel?: string;
/** Font size of the label for the cateogry axis, in pixels. */
categoryAxisLabelSize?: number;
/** Controls the distance between the category axis label and the category axis. */
categoryAxisLabelOffset?: number;
/** Label text for the value axis. */
valueAxisLabel?: string;
/** Font size of the label for the value axis, in pixels. */
valueAxisLabelSize?: number;
/** Controls the distance between the value axis label and the value axis. */
valueAxisLabelOffset?: number;
/** Margin for each item in the legend */
itemMargin?: string;
/** Minimum width of the graph. */
minWidth?: number;
/** Breakpoint width of graph where alernating labels are displayed. Only for Vertical graphs */
widthAlternatingLabel?: number;
/** Space added to the bottom of the graph to show overflowing labels. Only for Vertical graphs */
alternatingLabelSpace?: number;
/** Default position of labels in x-axis, in px. */
defaultLabelDy?: string;
/** Position of lower labels in x-axis, in px. Only for Vertical graphs */
lowerLabelDy?: string;
}
// Best format for props
interface GroupedBarGraphData {
category: string;
values: {
[key: string]: number;
};
}
// Best format for visx
interface BarGroupData {
category: string;
[key: string]: string | number;
}
// BAR_PADDING must be in the range [0, 1)
const BAR_PADDING = 0.2;
const DEFAULT_LABEL_SIZE = 16;
type TooltipData = string;
export const GroupedBarGraphVertical = withTooltip<GroupedBarGraphProps, TooltipData>(
({
data: propsData,
barColors,
barHoverColorsMap,
width,
height,
margin,
className,
minWidth = 500,
categoryTickLabelSize = DEFAULT_LABEL_SIZE,
valueTickLabelSize = DEFAULT_LABEL_SIZE,
hoverLabelSize,
categoryAxisLabel,
categoryAxisLabelSize = DEFAULT_LABEL_SIZE,
categoryAxisLabelOffset = 0,
valueAxisLabel,
valueAxisLabelSize = DEFAULT_LABEL_SIZE,
valueAxisLabelOffset = 0,
itemMargin = "0 0 0 15px",
widthAlternatingLabel = 600,
alternatingLabelSpace = 80,
defaultLabelDy = `0px`,
lowerLabelDy = `30px`,
tooltipOpen,
tooltipLeft,
tooltipTop,
tooltipData,
hideTooltip,
showTooltip,
}) => {
width = width < minWidth ? minWidth : width; // Ensuring graph's width >= minWidth
const alternatingLabel = width <= widthAlternatingLabel;
const final_margin_bottom = alternatingLabel ? margin.bottom + alternatingLabelSpace : margin.bottom;
const data: BarGroupData[] = propsData.map((datum: GroupedBarGraphData) => {
return { category: datum.category, ...datum.values };
});
const keys = Object.keys(propsData[0].values);
propsData.forEach((d: GroupedBarGraphData) => {
const currentKeys = Object.keys(d.values);
if (keys.length != currentKeys.length || !keys.every((key: string) => currentKeys.includes(key))) {
throw new Error("Every category in a GroupedBarGraph must have the same keys. Check the data prop");
}
});
const allValues = propsData.map((d: GroupedBarGraphData) => Object.values(d.values)).flat();
const categoryMax = width - margin.left - margin.right;
const valueMax = height - margin.top - final_margin_bottom;
const getCategory = (d: BarGroupData) => d.category;
const categoryScale = scaleBand({
domain: data.map(getCategory),
padding: BAR_PADDING,
});
const keyScale = scaleBand({
domain: keys,
});
const valueScale = scaleLinear<number>({
domain: [0, Math.max(...allValues)],
});
const colorScale = scaleOrdinal<string, string>({
domain: keys,
range: barColors,
});
categoryScale.rangeRound([0, categoryMax]);
keyScale.rangeRound([0, categoryScale.bandwidth()]);
valueScale.rangeRound([valueMax, 0]);
return (
<div className={className ? `${className} ${styles.wrapper}` : styles.wrapper}>
<div className={styles.legend}>
<LegendOrdinal scale={colorScale} direction="row" itemMargin={itemMargin} labelAlign="center" />
</div>
<svg width={width} height={height}>
<defs>
{Object.keys(barHoverColorsMap).map((color: string) => {
// remove brackets from colour name to make ids work
const colorId = removeBrackets(color);
return (
<filter key={`glow-${color}`} id={`glow-${colorId}`}>
<feDropShadow dx="0" dy="0" stdDeviation="4" floodColor={barHoverColorsMap[color]} />
</filter>
);
})}
</defs>
<Group top={margin.top} left={margin.left}>
<Group>
{data.map((d, idx) => {
const barName = `${getCategory(d)}-${idx}`;
const barWidth = categoryScale.bandwidth();
const backgroundBarWidth = barWidth / (1 - BAR_PADDING);
return idx % 2 === 0 ? (
<Bar
className={styles.barBackground}
key={`bar-${barName}-background`}
x={
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
categoryScale(getCategory(d))! - (backgroundBarWidth - barWidth) / 2
}
y={0}
width={backgroundBarWidth}
height={valueMax}
/>
) : null;
})}
</Group>
<GridRows scale={valueScale} width={categoryMax} numTicks={5} stroke={Color.label} strokeWidth={4} strokeDasharray="10" strokeLinecap="round" />
<BarGroup
data={data}
keys={keys}
height={valueMax}
x0={getCategory}
x0Scale={categoryScale}
x1Scale={keyScale}
yScale={valueScale}
color={colorScale}>
{(barGroups) =>
barGroups.map((barGroup) => (
<Group key={`bar-group-${barGroup.x0}-${barGroup.index}`} left={barGroup.x0}>
{barGroup.bars.map((bar) => (
<HoverableBar
onMouseMove={(e) => {
const tooltipPos = getTooltipPosition(e);
showTooltip({
tooltipData: bar.value.toString(),
tooltipTop: tooltipPos.y,
tooltipLeft: tooltipPos.x,
});
}}
onMouseOut={hideTooltip}
key={`bar-group-bar-${barGroup.x0}-${barGroup.index}-${bar.key}-${bar.index}`}
bar={bar}
valueMax={valueMax}
hoverFillColor={barHoverColorsMap[bar.color]}
hoverLabelSize={hoverLabelSize}
/>
))}
</Group>
))
}
</BarGroup>
<AxisBottom
scale={categoryScale}
top={valueMax}
hideAxisLine
hideTicks
tickLabelProps={(value, index) => {
const alternatingDy = index % 2 == 0 ? defaultLabelDy : lowerLabelDy;
return {
...bottomTickLabelProps,
className: styles.tickLabel,
dy: alternatingLabel ? alternatingDy : defaultLabelDy,
fontSize: `${categoryTickLabelSize / 16}rem`,
width: categoryScale.bandwidth(),
verticalAnchor: "start",
};
}}
label={categoryAxisLabel}
labelClassName={styles.axisLabel}
labelOffset={categoryAxisLabelOffset}
labelProps={{
fontSize: `${categoryAxisLabelSize / 16}rem`,
}}
/>
<AxisLeft
scale={valueScale}
hideAxisLine
hideTicks
numTicks={5}
tickLabelProps={() => {
return {
...leftTickLabelProps,
className: styles.tickLabel,
dx: "-0.5rem",
dy: "0.25rem",
fontSize: `${valueTickLabelSize / 16}rem`,
};
}}
label={valueAxisLabel}
labelClassName={styles.axisLabel}
labelOffset={valueAxisLabelOffset}
labelProps={{
fontSize: `${valueAxisLabelSize / 16}rem`,
}}
/>
</Group>
</svg>
{tooltipOpen && <TooltipWrapper top={tooltipTop} left={tooltipLeft} header={tooltipData as string}></TooltipWrapper>}
</div>
);
},
);
export const GroupedBarGraphHorizontal = withTooltip<GroupedBarGraphProps, TooltipData>(
({
data: propsData,
barColors,
barHoverColorsMap,
width,
height,
margin,
className,
minWidth = 600,
categoryTickLabelSize = DEFAULT_LABEL_SIZE,
valueTickLabelSize = DEFAULT_LABEL_SIZE,
hoverLabelSize,
categoryAxisLabel,
categoryAxisLabelSize = DEFAULT_LABEL_SIZE,
categoryAxisLabelOffset = 0,
valueAxisLabel,
valueAxisLabelSize = DEFAULT_LABEL_SIZE,
valueAxisLabelOffset = 0,
itemMargin = "0 0 0 15px",
defaultLabelDy = "0",
tooltipOpen,
tooltipLeft,
tooltipTop,
tooltipData,
hideTooltip,
showTooltip,
}) => {
width = width < minWidth ? minWidth : width; // Ensuring graph's width >= minWidth
const data: BarGroupData[] = propsData.map((datum: GroupedBarGraphData) => {
return { category: datum.category, ...datum.values };
});
const keys = Object.keys(propsData[0].values);
propsData.forEach((d: GroupedBarGraphData) => {
const currentKeys = Object.keys(d.values);
if (keys.length != currentKeys.length || !keys.every((key: string) => currentKeys.includes(key))) {
throw new Error("Every category in a GroupedBarGraph must have the same keys. Check the data prop");
}
});
const allValues = propsData.map((d: GroupedBarGraphData) => Object.values(d.values)).flat();
const categoryMax = height - margin.top - margin.bottom;
const valueMax = width - margin.left - margin.right;
const getCategory = (d: BarGroupData) => d.category;
const categoryScale = scaleBand({
domain: data.map(getCategory),
padding: BAR_PADDING,
});
const keyScale = scaleBand({
domain: keys,
});
const valueScale = scaleLinear<number>({
domain: [Math.max(...allValues), 0],
});
const colorScale = scaleOrdinal<string, string>({
domain: keys,
range: barColors,
});
categoryScale.rangeRound([0, categoryMax]);
keyScale.rangeRound([0, categoryScale.bandwidth()]);
valueScale.rangeRound([valueMax, 0]);
return (
<div className={className ? `${className} ${styles.wrapper}` : styles.wrapper}>
<div className={styles.legend}>
<LegendOrdinal scale={colorScale} direction="row" itemMargin={itemMargin} labelAlign="center" />
</div>
<svg width={width} height={height}>
<defs>
{Object.keys(barHoverColorsMap).map((color: string) => {
// remove brackets from colour name to make ids work
const colorId = removeBrackets(color);
return (
<filter key={`glow-${color}`} id={`glow-${colorId}`}>
<feDropShadow dx="0" dy="0" stdDeviation="4" floodColor={barHoverColorsMap[color]} />
</filter>
);
})}
</defs>
<Group top={margin.top} left={margin.left}>
<Group>
{data.map((d, idx) => {
const barName = `${getCategory(d)}-${idx}`;
const barWidth = categoryScale.bandwidth();
const backgroundBarWidth = barWidth / (1 - BAR_PADDING);
return idx % 2 === 0 ? (
<Bar
className={styles.barBackground}
key={`bar-${barName}-background`}
x={0}
y={
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
categoryScale(getCategory(d))! - (backgroundBarWidth - barWidth) / 2
}
width={valueMax}
height={backgroundBarWidth}
/>
) : null;
})}
</Group>
<GridColumns scale={valueScale} height={categoryMax} numTicks={5} stroke={Color.label} strokeWidth={4} strokeDasharray="10" strokeLinecap="round" />
<BarGroupHorizontal
data={data}
keys={keys}
width={valueMax}
y0={getCategory}
y0Scale={categoryScale}
y1Scale={keyScale}
xScale={valueScale}
color={colorScale}>
{(barGroups) =>
barGroups.map((barGroup) => (
<Group key={`bar-group-${barGroup.y0}-${barGroup.index}`} top={barGroup.y0}>
{barGroup.bars.map((bar) => (
<HoverableBar
onMouseMove={(e) => {
const tooltipPos = getTooltipPosition(e);
showTooltip({
tooltipData: bar.value.toString(),
tooltipLeft: tooltipPos.x,
tooltipTop: tooltipPos.y,
});
}}
onMouseOut={hideTooltip}
key={`bar-group-bar-${barGroup.y0}-${barGroup.index}-${bar.key}-${bar.index}`}
bar={bar}
valueMax={valueMax}
hoverFillColor={barHoverColorsMap[bar.color]}
hoverLabelSize={hoverLabelSize}
isHorizontal
/>
))}
</Group>
))
}
</BarGroupHorizontal>
<AxisLeft
scale={categoryScale}
hideAxisLine
hideTicks
tickLabelProps={() => {
return {
...leftTickLabelProps,
className: styles.tickLabel,
dx: "-0.5rem",
dy: defaultLabelDy,
fontSize: `${valueTickLabelSize / 16}rem`,
height: categoryScale.bandwidth(),
};
}}
label={categoryAxisLabel}
labelClassName={styles.axisLabel}
labelOffset={categoryAxisLabelOffset}
labelProps={{
fontSize: `${categoryAxisLabelSize / 16}rem`,
}}
/>
<AxisBottom
scale={valueScale}
top={categoryMax}
hideAxisLine
hideTicks
numTicks={5}
tickLabelProps={() => {
return {
...bottomTickLabelProps,
className: styles.tickLabel,
dy: "-0.25rem",
fontSize: `${categoryTickLabelSize / 16}rem`,
verticalAnchor: "start",
};
}}
label={valueAxisLabel}
labelClassName={styles.axisLabel}
labelOffset={valueAxisLabelOffset}
labelProps={{
fontSize: `${valueAxisLabelSize / 16}rem`,
}}
/>
</Group>
</svg>
{tooltipOpen && <TooltipWrapper top={tooltipTop} left={tooltipLeft} header={tooltipData as string}></TooltipWrapper>}
</div>
);
},
);
interface HoverableBarProps {
bar: BarGroupBarType<string>;
valueMax: number;
hoverFillColor?: string;
hoverLabelSize?: number;
isHorizontal?: boolean;
onMouseMove?: (e: React.MouseEvent<SVGPathElement, MouseEvent>) => void;
onMouseOut?: () => void;
}
function HoverableBar(props: HoverableBarProps) {
const { bar, hoverFillColor, onMouseMove, onMouseOut } = props;
const [isHovered, setIsHovered] = useState(false);
const colorId = removeBrackets(bar.color);
return (
<Group
className={styles.singleBar}
onMouseEnter={() => {
setIsHovered(true);
}}
onMouseLeave={() => {
setIsHovered(false);
}}>
<Bar
className={styles.bar}
onMouseMove={onMouseMove}
onMouseOut={onMouseOut}
x={bar.x}
y={bar.y}
width={bar.width}
height={bar.height}
fill={isHovered && hoverFillColor ? hoverFillColor : bar.color}
// apply the glow effect when the bar is hovered
filter={isHovered ? `url(#glow-${colorId})` : undefined}
/>
</Group>
);
}
function removeBrackets(str: string) {
return str.replace(/\(|\)/g, "");
}

View File

@ -0,0 +1,146 @@
.headerWrapper {
display: flex;
justify-content: space-between;
align-items: center;
position: sticky;
top: 0;
left: 0;
z-index: 98;
box-sizing: border-box;
padding-left: 6.25rem;
padding-right: 6.25rem;
}
.titleHeader {
margin: calc(16rem / 16) 0;
}
.sideBarCommon {
position: fixed;
right: 0;
top: 0;
min-width: calc(400rem / 16);
height: 100vh;
background: var(--secondary-background);
padding: calc(100rem / 16);
margin: 0;
z-index: 100;
padding: 0;
padding-right: calc(20rem / 16);
transition: transform 0.4s;
overflow: auto;
}
.sideBarShown {
composes: sideBarCommon;
}
.sideBarHidden {
composes: sideBarCommon;
transform: translateX(100%);
}
.backgroundTintCommon {
background-color: var(--label-overlay);
animation: fadeIn 1s;
position: fixed;
z-index: 99;
left: 0;
top: 0;
width: 100vw;
height: 100vh;
transition:
opacity 0.8s,
visibility 0.8s;
}
.backgroundTintShow {
composes: backgroundTintCommon;
visibility: visible;
opacity: 0.6;
}
.backgroundTintHidden {
composes: backgroundTintCommon;
visibility: hidden;
opacity: 0;
}
.menuHeader {
margin-bottom: 0;
padding-left: calc(30rem / 16);
padding-bottom: 0;
color: var(--dark--secondary-heading);
}
.sectionsWrapper {
padding-left: calc(30rem / 16);
}
.menuIcon {
background: none;
border: none;
}
.menuIcon:hover {
cursor: pointer;
}
.menuIconSvg {
stroke: var(--menu-icon);
stroke-width: 10;
stroke-linecap: round;
transition: stroke 120ms linear;
}
.menuIconSvg:hover {
stroke: var(--menu-icon-hover);
}
@media screen and (max-width: 768px) {
.sideBarCommon {
min-width: calc(300rem / 16);
max-width: calc(500rem / 16);
}
.menuHeader {
padding-left: calc(20rem / 16);
}
.sectionsWrapper {
padding-left: calc(20rem / 16);
}
.headerWrapper {
padding: calc(10rem / 16) calc(20rem / 16) 0;
}
}
.closeMenuButton {
background: var(--primary-heading);
padding: 0 calc(20rem / 16);
border-radius: calc(50rem / 16);
display: flex;
flex-direction: row;
margin-left: calc(20rem / 16);
/* transparent border fixes weird coloring on the border in some browsers */
border: calc(1rem / 16) solid transparent;
transition: background-color 0.25s ease-out;
}
.closeMenuButton:hover {
background-color: var(--secondary-accent-lighter);
cursor: pointer;
}
.lineWrapper {
width: 100%;
display: flex;
}
.lineWrapper:before {
content: "";
flex: 1 1;
border-bottom: 3px solid white;
margin: auto;
}

64
components/Header.tsx Normal file
View File

@ -0,0 +1,64 @@
"use client";
import { pageRoutes } from "@/data/routes";
import { useWindowScroll } from "@uidotdev/usehooks";
import Image from "next/legacy/image";
import Link from "next/link";
import { useState } from "react";
import styles from "./Header.module.css";
import { Sections } from "./Sections";
export function Header() {
const [isShowingMenu, setIsShowingMenu] = useState(false);
const [state] = useWindowScroll();
const verticalPadding = `${0.75 - Math.min(0.5, (state.y ?? 0) / 400)}rem`;
return (
<>
<div
className={isShowingMenu ? styles.backgroundTintShow : styles.backgroundTintHidden}
onClick={() => {
setIsShowingMenu(false);
}}
/>
<div
className={styles.headerWrapper}
style={{
backgroundColor: `rgb(var(--navbar-background-rgb), ${(state.y ?? 0) / 200})`,
paddingTop: verticalPadding,
paddingBottom: verticalPadding,
}}>
<h1 className={styles.titleHeader} style={{ fontSize: `${3 - Math.min(0.5, (state.y ?? 0) / 400)}rem` }}>
<Link href="/">CS 2023</Link>
</h1>
<button
onClick={() => {
setIsShowingMenu(true);
}}
className={styles.menuIcon}>
<svg className={styles.menuIconSvg} width="50" height="100" viewBox="0 0 144 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<line x1="139" y1="5" x2="5.00003" y2="4.99999" />
<line x1="139" y1="50" x2="5.00003" y2="50" />
<line x1="139" y1="95" x2="5.00003" y2="95" />
</svg>
</button>
</div>
<div className={isShowingMenu ? styles.sideBarShown : styles.sideBarHidden}>
<h1 className={styles.menuHeader}>Sections</h1>
<div className={styles.lineWrapper}>
<button
className={styles.closeMenuButton}
onClick={() => {
setIsShowingMenu(false);
}}>
<Image src="/images/rightArrow.svg" alt="Right Arrow" className={styles.arrowIcon} width="50" height="50" draggable="false" />
</button>
</div>
<div className={styles.sectionsWrapper}>
<Sections data={pageRoutes} showHeader={false} />
</div>
</div>
</>
);
}

View File

@ -0,0 +1,32 @@
.tickLabel {
font-family: "Lexend", sans-serif;
font-weight: 800;
fill: var(--label);
}
.line {
transition: filter 0.5s ease-out;
}
.line:hover {
filter: drop-shadow(0 0 calc(4rem / 16) var(--primary-accent));
transition: filter 0.5s ease-out;
}
.wrapper {
display: flex;
width: min-content;
}
.legend {
display: flex;
margin: calc(16rem / 8);
justify-content: center;
}
@media screen and (max-width: 900px) {
/* To fix legend being cut off on mobile */
.legend {
justify-content: start;
}
}

227
components/LineGraph.tsx Normal file
View File

@ -0,0 +1,227 @@
import { AxisBottom, AxisLeft } from "@visx/axis";
import { bottomTickLabelProps } from "@visx/axis/lib/axis/AxisBottom";
import { leftTickLabelProps } from "@visx/axis/lib/axis/AxisLeft";
import { GridColumns, GridRows } from "@visx/grid";
import { Group } from "@visx/group";
import { LegendOrdinal } from "@visx/legend";
import { scaleBand, scaleLinear, scaleOrdinal } from "@visx/scale";
import { LinePath } from "@visx/shape";
import { withTooltip } from "@visx/tooltip";
import React from "react";
import { Color } from "@/utils/Color";
import { getTooltipPosition, TooltipWrapper } from "./TooltipWrapper";
import styles from "./LineGraph.module.css";
interface LineData {
label: string;
yValues: number[];
}
interface PointData {
x: string;
y: number;
}
interface LineGraphData {
xValues: string[];
lines: LineData[];
}
interface LineGraphProps {
data: LineGraphData;
/** Width of the entire graph, in pixels. */
width: number;
/** Height of the entire graph, in pixels. */
height: number;
/** Distance between the edge of the graph and the area where the bars are drawn, in pixels. */
margin: {
top: number;
bottom: number;
left: number;
right: number;
};
/** List of hexademical colours for each line, length of colorRange should match the length of data. */
colorRange: string[];
/** Font size of the category tick labels, in pixels. Default is 16px. */
xTickLabelSize?: number;
/** Font size of the value tick labels, in pixels. Default is 16px. */
yTickLabelSize?: number;
/** Margin for each item in the legend */
itemMargin?: string;
/** Minimum width of the graph. */
minWidth?: number;
}
const DEFAULT_LABEL_SIZE = 16;
type TooltipData = string;
export const LineGraph = withTooltip<LineGraphProps, TooltipData>(
({
width,
height,
margin,
data,
colorRange,
xTickLabelSize = DEFAULT_LABEL_SIZE,
yTickLabelSize = DEFAULT_LABEL_SIZE,
tooltipOpen,
tooltipLeft,
tooltipTop,
tooltipData,
hideTooltip,
showTooltip,
itemMargin = "0 0 0 15px",
minWidth = 500,
}) => {
if (width < minWidth) {
width = minWidth;
}
const xLength = data.xValues.length;
if (data.lines.length != colorRange.length) {
throw new Error("Invalid data with wrong length.");
}
data.lines.forEach((line) => {
if (line.yValues.length != xLength) {
throw new Error("Invalid data with wrong length.");
}
});
const yMax = height - margin.top - margin.bottom;
const xMax = width - margin.left - margin.right;
const actualData = data.lines.map((line) => {
return line.yValues.map((val, idx) => {
return { x: data.xValues[idx], y: val };
});
});
const yMaxValue = Math.max(
...data.lines.map((line) => {
return Math.max(...line.yValues);
}),
);
// data accessors
const getX = (d: PointData) => d.x;
const getY = (d: PointData) => d.y;
// scales
const xScale = scaleBand({
range: [0, xMax],
domain: data.xValues,
});
const yScale = scaleLinear<number>({
range: [0, yMax],
nice: true,
domain: [yMaxValue, 0],
});
const keys = data.lines.map((line) => line.label);
const colorScale = scaleOrdinal<string, string>({
domain: keys,
range: colorRange,
});
return (
<div>
<div className={styles.legend}>
<LegendOrdinal scale={colorScale} direction="row" itemMargin={itemMargin} labelAlign="center" />
</div>
<svg width={width} height={height}>
<Group top={margin.top} left={margin.left}>
<GridColumns
scale={xScale}
height={yMax}
left={margin.left}
numTicks={5}
stroke={Color.tertiaryBackground}
strokeWidth={4}
strokeDasharray="10"
strokeLinecap="round"
/>
<GridRows
scale={yScale}
width={xMax}
left={margin.left * 2.3}
numTicks={data.xValues.length}
stroke={Color.tertiaryBackground}
strokeWidth={4}
strokeDasharray="10"
strokeLinecap="round"
/>
<AxisBottom
scale={xScale}
top={margin.top + yMax}
left={margin.left}
hideAxisLine
hideTicks
tickLabelProps={() => {
return {
...bottomTickLabelProps,
className: styles.tickLabel,
dy: "-0.25rem",
fontSize: `${xTickLabelSize / 16}rem`,
width: xScale.bandwidth(),
};
}}
/>
<AxisLeft
scale={yScale}
left={margin.left}
hideAxisLine
hideTicks
numTicks={5}
tickLabelProps={() => {
return {
...leftTickLabelProps,
className: styles.tickLabel,
dx: "1.25rem",
dy: "0.25rem",
fontSize: `${yTickLabelSize / 16}rem`,
};
}}
/>
<Group left={margin.left + xMax / (data.xValues.length * 2)}>
{actualData.map((lineData, i) => {
return (
<Group key={`line-${i}`}>
<LinePath
onMouseMove={(e) => {
const tooltipPos = getTooltipPosition(e);
showTooltip({
tooltipData: data.lines[i].label,
tooltipLeft: tooltipPos.x,
tooltipTop: tooltipPos.y,
});
}}
onMouseOut={hideTooltip}
data={lineData}
className={styles.line}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
x={(d) => xScale(getX(d))!}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
y={(d) => yScale(getY(d))!}
stroke={colorRange[i]}
strokeWidth={4}
strokeOpacity={2}
/>
</Group>
);
})}
</Group>
</Group>
</svg>
{tooltipOpen && <TooltipWrapper top={tooltipTop} left={tooltipLeft} header={tooltipData as string}></TooltipWrapper>}
</div>
);
},
);

View File

@ -0,0 +1,9 @@
.textbox {
display: flex;
flex-direction: column;
width: 80%;
padding: calc(80rem / 16);
background-color: var(--side-panel);
border-radius: calc(20rem / 16);
align-self: center;
}

11
components/Panel.tsx Normal file
View File

@ -0,0 +1,11 @@
import { ReactNode } from "react";
import styles from "./Panel.module.css";
export interface TextboxProps {
children: ReactNode;
}
export function Panel({ children }: TextboxProps) {
return <section className={styles.textbox}>{children}</section>;
}

View File

@ -0,0 +1,35 @@
.piePathWithBackground {
fill: var(--chart-blue-light); /* Light Green Colour */
/* fill: var(--tertiary-background); Gray Colour*/
stroke: var(--label);
stroke-width: 1px;
stroke-dasharray: 0;
stroke-linecap: round;
transition: fill 0.5s ease-out;
}
.piePathWithoutBackground {
fill: var(--chart-pink-light);
stroke: var(--label);
stroke-width: 1px;
stroke-dasharray: 0;
stroke-linecap: round;
transition: fill 0.5s ease-out;
}
.labelPath {
fill-opacity: 0;
}
.labelText {
fill: white;
}
.group:hover > .piePathWithBackground {
fill: var(--chart-blue-heavy);
filter: drop-shadow(0px 0px calc(6rem / 16) var(--chart-blue-heavy));
}
.group:hover > .piePathWithoutBackground {
fill: var(--chart-pink-heavy);
filter: drop-shadow(0px 0px calc(6rem / 16) var(--chart-pink-heavy));
}

172
components/PieChart.tsx Normal file
View File

@ -0,0 +1,172 @@
import { Group } from "@visx/group";
import Pie, { ProvidedProps } from "@visx/shape/lib/shapes/Pie";
import { Text } from "@visx/text";
import { withTooltip } from "@visx/tooltip";
import { getTooltipPosition, TooltipWrapper } from "./TooltipWrapper";
import styles from "./PieChart.module.css";
interface PieChartProps {
data: PieChartData[];
/** Width of the entire graph, including labels, in pixels. */
width: number;
/** Width of the outer ring of labels, in pixels. Label text may be cut off if specified value is too small. */
labelWidth: number;
/** Distance between pie slices, in pixels. */
padRadius?: number;
/** Distance of gap in center of pie graph, in pixels. */
innerRadius?: number;
/** Font size of labels outside the pie, in pixels. */
labelTextSize?: number;
/** X-axis offset of the label text, in pixels. */
labelTextXOffset?: number;
/** Y-axis offset of the label text, in pixels. */
labelTextYOffset?: number;
/** The radial offset of the label text, in pixels. */
labelTextRadialOffset?: number;
/** If set, the minimum width of this graph */
minWidth?: number;
/** Accessor function to get value to display as label text from datum. */
getLabelDisplayValueFromDatum?: (datum: PieChartData) => string;
className?: string;
/** Has a Background block or not */
background?: boolean;
}
interface PieChartData {
category: string;
value: number;
}
export const PieChart = withTooltip<PieChartProps>(
({
data,
width,
labelWidth,
padRadius = width * 0.25,
innerRadius = width * 0,
labelTextSize = 40,
labelTextXOffset = 0,
labelTextYOffset = 0,
labelTextRadialOffset = -20,
minWidth = 500,
getLabelDisplayValueFromDatum = (datum: PieChartData) => `${datum.category}`,
className,
tooltipOpen,
tooltipLeft,
tooltipTop,
tooltipData,
hideTooltip,
showTooltip,
background = false,
}) => {
if (minWidth) {
width = width < minWidth ? minWidth : width;
}
const pieWidth = width * 0.5 - labelWidth;
const cornerRadius = 0;
const padAngle = 0;
const responsiveLabelTextSize = Math.min(labelTextSize, width / 10);
const sum = data.map((x) => x.value).reduce((x, y) => x + y);
const piePathClassName = background ? styles.piePathWithBackground : styles.piePathWithoutBackground;
return (
<div>
<svg className={className} width={width} height={width}>
<Group top={width * 0.5} left={width * 0.5}>
<Pie
data={data}
pieValue={(d: PieChartData) => d.value}
cornerRadius={cornerRadius}
padAngle={padAngle}
padRadius={padRadius}
innerRadius={innerRadius}
outerRadius={pieWidth}>
{({ arcs, path }) => {
return arcs.map((arc) => {
const pathArc = path(arc) as string;
return (
<Group className={styles.group} key={`arc-${arc.data.category}`}>
<path
onMouseMove={(e) => {
const tooltipPos = getTooltipPosition(e);
showTooltip({
tooltipData: `${arc.data.category}: ${arc.data.value} (${((arc.data.value / sum) * 100).toFixed(2)}%)`,
tooltipLeft: tooltipPos.x,
tooltipTop: tooltipPos.y,
});
}}
onMouseOut={hideTooltip}
className={piePathClassName}
d={pathArc}
/>
</Group>
);
});
}}
</Pie>
<Pie data={data} pieValue={(d: PieChartData) => d.value} innerRadius={pieWidth} outerRadius={width * 0.5}>
{(pie) => (
<PieSliceLabel
{...pie}
labelTextSize={responsiveLabelTextSize}
labelTextXOffset={labelTextXOffset}
labelTextYOffset={labelTextYOffset}
labelTextRadialOffset={labelTextRadialOffset}
getLabelDisplayValueFromDatum={getLabelDisplayValueFromDatum}
/>
)}
</Pie>
</Group>
</svg>
{tooltipOpen && <TooltipWrapper top={tooltipTop} left={tooltipLeft} header={tooltipData as string}></TooltipWrapper>}
</div>
);
},
);
type PieSliceLabelProps<PieChartData> = ProvidedProps<PieChartData> & {
labelTextSize: number;
labelTextXOffset: number;
labelTextYOffset: number;
labelTextRadialOffset: number;
getLabelDisplayValueFromDatum: (datum: PieChartData) => string;
};
export function PieSliceLabel({
path,
arcs,
labelTextSize,
labelTextXOffset,
labelTextYOffset,
labelTextRadialOffset,
getLabelDisplayValueFromDatum,
}: PieSliceLabelProps<PieChartData>) {
return (
<>
{arcs.map((arc) => {
const [centroidX, centroidY] = path.centroid(arc);
const pathArc = path(arc) as string;
return (
<Group className={styles.group} key={`arc-${arc.data.category}`}>
<path className={styles.labelPath} d={pathArc} />
<Text
className={styles.labelText}
x={(labelTextRadialOffset * centroidX) / Math.sqrt(centroidX ** 2 + centroidY ** 2) + centroidX + labelTextXOffset}
y={(labelTextRadialOffset * centroidY) / Math.sqrt(centroidX ** 2 + centroidY ** 2) + centroidY + labelTextYOffset}
textAnchor={centroidX > 100 ? "start" : centroidX < -100 ? "end" : "middle"}
fontSize={labelTextSize}>
{`${getLabelDisplayValueFromDatum(arc.data)}`}
</Text>
</Group>
);
})}
</>
);
}

View File

@ -0,0 +1,194 @@
.carousel {
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
gap: calc(8rem / 16);
margin: auto;
}
.circle {
position: absolute;
top: 30%;
right: 52%;
z-index: -1;
background-color: var(--tertiary-background);
clip-path: circle();
}
.right.circle {
top: unset;
right: unset;
bottom: 30%;
left: 52%;
}
.carouselButton {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: calc(16rem / 16);
height: min-content;
background: none;
border: none;
cursor: pointer;
}
.arrow {
position: relative;
width: calc(20rem / 16);
height: calc(40rem / 16);
transition: 0.2s;
}
.previous.arrow {
transform: rotate(180deg);
}
.carouselButton:hover > .arrow {
translate: calc(4rem / 16);
}
.carouselButton:hover > .previous.arrow {
translate: calc(-4rem / 16);
}
.withBackgroundCard {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: stretch;
gap: calc(16rem / 16);
min-height: inherit;
height: 100%;
width: 100%;
padding: calc(30rem / 16);
background-color: var(--chart-green-heavy);
border: calc(2rem / 16) solid var(--primary-text);
border-radius: calc(12rem / 16);
box-shadow: 0 calc(1rem / 16) calc(10rem / 16) var(--chart-green-light);
}
.withBackgroundCard ul {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: relative;
width: 100%;
margin: 0;
padding: 0;
flex-grow: 1;
}
.withBackgroundCard li {
position: absolute;
left: 0;
right: 0;
margin: 0;
padding: 0;
list-style: none;
visibility: visible;
opacity: 1;
transition: 0.1s;
}
.withBackgroundCard li.hidden {
visibility: hidden;
opacity: 0;
}
.withBackgroundCard p {
margin: 0 calc(16rem / 16);
font-weight: bold;
text-align: center;
}
.card {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: stretch;
gap: calc(16rem / 16);
min-height: inherit;
height: 100%;
width: 100%;
padding: calc(30rem / 16);
background-color: var(--tertiary-background);
border: calc(2rem / 16) solid var(--primary-text);
border-radius: calc(12rem / 16);
box-shadow: 0 calc(1rem / 16) calc(10rem / 16) var(--primary-accent);
}
.card ul {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: relative;
width: 100%;
margin: 0;
padding: 0;
flex-grow: 1;
}
.card li {
position: absolute;
left: 0;
right: 0;
margin: 0;
padding: 0;
list-style: none;
visibility: visible;
opacity: 1;
transition: 0.1s;
height: 100%;
display: flex;
overflow-y: scroll;
}
.card li.hidden {
visibility: hidden;
opacity: 0;
}
.card p {
margin: auto calc(16rem / 16);
font-weight: bold;
text-align: center;
height: max-content;
width: 100%;
}
.quotationMark {
width: calc(20rem / 16);
height: calc(20rem / 16);
}
.right.quotationMark {
transform: rotate(180deg);
align-self: end;
}
.bottomRow {
display: flex;
flex-direction: row;
justify-content: space-between;
width: 100%;
}

View File

@ -0,0 +1,111 @@
import { Color } from "@/utils/Color";
import { useState } from "react";
import styles from "./QuotationCarousel.module.css";
interface QuotationCarouselProps {
data: string[];
/** Width of the entire carousel including the buttons, in px. */
width?: number;
/** Minimum height of the carousel, in px. */
height?: number;
/** Diameter of the background circles, in px. Set to 0 for no circles. */
circleDiameter?: number;
className?: string;
/** Minimum width of the graph. */
minWidth?: number;
}
interface CarouselButtonProps {
onClick: () => void;
isPrevious?: boolean;
}
export function QuotationCarousel(props: QuotationCarouselProps) {
const { data, width = 600, height = 100, circleDiameter = 120, minWidth = 600, className } = props;
const actualWidth = width < minWidth ? minWidth : width;
const [activeIdx, setActiveIdx] = useState(0);
function showNextCard() {
setActiveIdx((activeIdx + 1) % data.length);
}
function showPreviousCard() {
setActiveIdx((activeIdx - 1 + data.length) % data.length);
}
return (
<section
className={className ? `${className} ${styles.carousel}` : styles.carousel}
style={{
width: `${actualWidth / 16}rem`,
minHeight: `${height / 16}rem`,
}}>
<Circle className={styles.circle} diameter={circleDiameter} />
<Circle className={`${styles.right} ${styles.circle}`} diameter={circleDiameter} />
<CarouselButton onClick={showPreviousCard} isPrevious />
<div className={styles.card}>
<QuotationMark className={styles.quotationMark} />
<ul>
{data.map((quote, idx) => (
<li key={idx} className={idx !== activeIdx ? styles.hidden : ""}>
<p>{quote}</p>
</li>
))}
</ul>
<div className={styles.bottomRow}>
<span>
{activeIdx + 1}/{data.length}
</span>
<QuotationMark className={`${styles.right} ${styles.quotationMark}`} />
</div>
</div>
<CarouselButton onClick={showNextCard} />
</section>
);
}
function Circle({ className, diameter }: { className: string; diameter: number }) {
return (
<div
className={className}
aria-hidden
style={{
width: `${diameter / 16}rem`,
height: `${diameter / 16}rem`,
}}
/>
);
}
function CarouselButton({ isPrevious, onClick }: CarouselButtonProps) {
return (
<button className={styles.carouselButton} onClick={onClick}>
<svg
className={isPrevious ? `${styles.previous} ${styles.arrow}` : styles.arrow}
width="39"
height="72"
viewBox="0 0 39 72"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M4 4L34.4206 35.804C35.2926 36.7157 35.2597 38.1619 34.3471 39.0329L4 68"
stroke={Color.primaryAccentLighter}
strokeWidth="4"
strokeLinecap="round"
/>
</svg>
</button>
);
}
function QuotationMark({ className }: { className: string }) {
return (
<svg className={className} aria-hidden width="68" height="56" viewBox="0 0 68 56" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M21.34 0.855375L31.1131 9.91768C28.9808 11.9315 27.0262 13.9454 25.2492 15.9592C23.5908 17.9731 22.2877 19.9869 21.34 22.0008C20.3923 24.0146 19.9185 25.9692 19.9185 27.8646C19.9185 29.4046 20.3331 30.7077 21.1623 31.7738C21.9915 32.84 22.9392 33.8469 24.0054 34.7946C25.0715 35.7423 26.0192 36.8677 26.8485 38.1708C27.6777 39.4738 28.0923 41.1323 28.0923 43.1461C28.0923 46.5815 26.8485 49.5431 24.3608 52.0308C21.9915 54.5185 18.8523 55.7623 14.9431 55.7623C11.1523 55.7623 7.71693 54.2223 4.63693 51.1423C1.67539 48.0623 0.194616 44.1531 0.194616 39.4146C0.194616 35.6238 0.964617 31.7146 2.50462 27.6869C4.16308 23.5408 6.53231 19.2169 9.61231 14.7154C12.6923 10.2138 16.6015 5.59383 21.34 0.855375ZM57.7669 0.855375L67.54 9.91768C65.4077 11.9315 63.4531 13.9454 61.6762 15.9592C60.0177 17.9731 58.7146 19.9869 57.7669 22.0008C56.8192 24.0146 56.3454 25.9692 56.3454 27.8646C56.3454 29.4046 56.76 30.7077 57.5892 31.7738C58.4185 32.84 59.3662 33.8469 60.4323 34.7946C61.4985 35.7423 62.4462 36.8677 63.2754 38.1708C64.1046 39.4738 64.5192 41.1323 64.5192 43.1461C64.5192 46.5815 63.2754 49.5431 60.7877 52.0308C58.4185 54.5185 55.2792 55.7623 51.37 55.7623C47.5792 55.7623 44.1439 54.2223 41.0639 51.1423C38.1023 48.0623 36.6215 44.1531 36.6215 39.4146C36.6215 35.6238 37.3915 31.7146 38.9315 27.6869C40.59 23.5408 42.9592 19.2169 46.0392 14.7154C49.1192 10.2138 53.0285 5.59383 57.7669 0.855375Z"
fill={Color.primaryText}
/>
</svg>
);
}

View File

@ -0,0 +1,36 @@
.header {
display: flex;
flex-direction: column;
justify-content: center;
padding: calc(40rem / 16) 0;
text-align: center;
}
.title {
background: linear-gradient(281deg, #91f1ac 57.31%, #5caff9 94.83%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-size: calc(70rem / 16);
margin: calc(40rem / 16) auto;
word-break: break-word;
}
.subTitle {
max-width: min(90vw, 40rem);
color: var(--primary-accent-lighter);
font-size: calc(26rem / 16);
margin: auto;
}
@media screen and (max-width: 900px) {
.title {
font-size: calc(50rem / 16);
margin: calc(20rem / 16) auto;
}
.subTitle {
font-size: calc(30rem / 16);
margin: auto calc(15rem / 16);
}
}

View File

@ -0,0 +1,19 @@
import { GooseAndMoon } from "./GooseAndMoon";
import styles from "./SectionHeader.module.css";
interface SectionHeaderProps {
title: string;
subtitle?: string;
}
export function SectionHeader({ title, subtitle }: SectionHeaderProps) {
return (
<>
<GooseAndMoon />
<div className={styles.header}>
<h1 className={styles.title}>{title}</h1>
{subtitle && <h5 className={styles.subTitle}>{subtitle}</h5>}
</div>
</>
);
}

View File

@ -0,0 +1,11 @@
.sectionWrapper h2 {
color: var(--primary-heading);
padding-left: 4rem;
}
@media screen and (max-width: 900px) {
.sectionWrapper h2 {
text-align: center;
padding-left: 0;
}
}

View File

@ -0,0 +1,15 @@
import React from "react";
import styles from "./SectionWrapper.module.css";
type SectionWrapperProps = {
title: string;
};
export function SectionWrapper({ title }: SectionWrapperProps) {
return (
<div className={styles.sectionWrapper}>
<h2>{title}</h2>
</div>
);
}

View File

@ -0,0 +1,86 @@
.sections {
display: flex;
flex-direction: row;
gap: calc(15rem / 16);
}
.sections h1 {
flex: 3;
text-align: right;
margin: 0;
}
.separator {
flex: 1;
background-color: var(--label);
height: calc(1rem / 16);
width: 100%;
margin-top: calc(30rem / 16);
}
.nav {
flex: 4;
display: flex;
flex-direction: column;
}
.nav ul {
list-style-type: none;
margin: 0;
padding: 0;
}
.nav li {
margin: calc(20rem / 16);
margin-left: 0;
}
.nav li:first-child {
margin-top: calc(18rem / 16);
}
.nav li .linkNumber {
color: var(--secondary-accent);
margin: 0;
display: inline;
}
.nav li a {
font-size: calc(24rem / 16);
color: var(--primary-text);
}
.linkName:after {
content: "";
position: absolute;
width: 100%;
transform: scaleX(0);
height: calc(1rem / 16);
bottom: 0;
left: 0;
background-color: var(--primary-text);
cursor: pointer;
transform-origin: bottom right;
transition: transform 0.25s ease-out;
}
.linkName:hover:after {
transform: scaleX(1);
transform-origin: bottom left;
}
.linkName {
margin: 0;
display: inline;
position: relative;
}
@media screen and (max-width: 900px) {
.sections {
flex-direction: column;
}
.sections h1 {
text-align: left;
}
}

45
components/Sections.tsx Normal file
View File

@ -0,0 +1,45 @@
import { PageRoutes } from "@/data/routes";
import Link from "next/link";
import React from "react";
import styles from "./Sections.module.css";
interface SectionsProps {
/* Whether to display the "Sections" title and separator that appears on the left. */
showHeader?: boolean;
/* Width of the entire Sections, in px. */
width?: number;
data: PageRoutes;
className?: string;
}
export function Sections({ data, showHeader = true, className }: SectionsProps) {
return (
<section className={className ? `${className} ${styles.sections}` : `${styles.sections}`}>
{showHeader ? (
<>
<h1>Sections</h1>
<div className={styles.separator} />
</>
) : (
""
)}
<nav className={styles.nav}>
<ul>
{Object.values(data).map((datum, index) => {
return (
<li key={`${datum.name}-${index}`}>
<span className={styles.linkNumber}>{String(index).padStart(2, "0")} </span>
<span className={styles.linkName}>
<Link className={styles.linkName} href={datum.url}>
{datum.name}
</Link>
</span>
</li>
);
})}
</ul>
</nav>
</section>
);
}

View File

@ -0,0 +1,23 @@
.container {
position: relative;
}
.barStack {
transition: filter 0.5s ease-out;
}
.barStack:hover {
filter: drop-shadow(0 0 calc(4rem / 16) var(--label));
transition: filter 0.5s ease-out;
}
.legend {
display: flex;
font-size: calc(16rem / 16);
top: 0;
justify-content: center;
}
.key {
font-weight: bold;
}

View File

@ -0,0 +1,424 @@
import { AxisLeft, AxisBottom } from "@visx/axis";
import { GridRows, GridColumns } from "@visx/grid";
import { Group } from "@visx/group";
import { LegendOrdinal } from "@visx/legend";
import { Point } from "@visx/point";
import { scaleBand, scaleLinear, scaleOrdinal } from "@visx/scale";
import { BarStack, BarStackHorizontal, Line } from "@visx/shape";
import { SeriesPoint } from "@visx/shape/lib/types";
import { withTooltip } from "@visx/tooltip";
import { WithTooltipProvidedProps } from "@visx/tooltip/lib/enhancers/withTooltip";
import React from "react";
import { Color } from "@/utils/Color";
import { getTooltipPosition, TooltipWrapper } from "./TooltipWrapper";
import styles from "./StackedBarGraph.module.css";
interface StackedBarData {
category: string;
[key: string]: number | string;
}
type TooltipData = {
bar: SeriesPoint<StackedBarData>;
key: string;
index: number;
height: number;
width: number;
x: number;
y: number;
color: string;
};
export type StackedBarProps = {
data: StackedBarData[];
/** Width of the entire graph, in pixels, greater than 10. */
width: number;
/** Height of the entire graph, in pixels. */
height: number;
/** Names of the groups appearing in the legend */
keys: string[];
/** Colours for each key */
colorRange: string[];
/** Distance between the edge of the graph and the area where the bars are drawn, in pixels. */
margin: { top: number; left: number; right: number; bottom: number };
/** Number of ticks for the value axis */
numTicksValueAxis?: number;
/** Width of the lines in the graph, in px. */
strokeWidth?: number;
/** Length of the dashes and the gaps in the graph, in px. */
strokeDashArray?: string;
/** Padding between each bar in the stacked bar graph, from 0 to 1 */
scalePadding?: number;
/** Margin for each item in the legend */
itemMargin?: string;
/** Hide the first data value in tooltip*/
hideDataValueInTooltip?: boolean;
//** Top tooltip label */
tooltipTopLabel?: string;
//** Bottom tooltip label */
tooltipBottomLabel?: string;
//** Display percentage */
displayPercentage?: boolean;
/** Minimum width of the graph. */
minWidth?: number;
};
let tooltipTimeout: number;
export const StackedBarGraphVertical = withTooltip<StackedBarProps, TooltipData>(
({
data,
width,
height,
keys,
colorRange,
margin,
scalePadding = 0.3,
numTicksValueAxis = 6,
strokeWidth = 2.5,
strokeDashArray = "10,4",
itemMargin = "0 0 0 15px",
tooltipOpen,
tooltipLeft,
tooltipTop,
tooltipData,
hideTooltip,
showTooltip,
hideDataValueInTooltip,
tooltipBottomLabel = "",
tooltipTopLabel = "",
displayPercentage,
minWidth = 500,
}: StackedBarProps & WithTooltipProvidedProps<TooltipData>) => {
if (width < minWidth) {
width = minWidth;
}
const yTotals = data.reduce((allTotals, currCategory) => {
const yTotal = keys.reduce((categoryTotal, k) => {
categoryTotal += currCategory[k] as number;
return categoryTotal;
}, 0);
allTotals.push(yTotal);
return allTotals;
}, [] as number[]);
const TICK_LABEL_FONT_WEIGHT = 800;
// accessors
const getCategory = (d: StackedBarData) => d.category;
// scales
const categoryScale = scaleBand<string>({
domain: data.map(getCategory),
padding: scalePadding,
});
const valueScale = scaleLinear<number>({
domain: [0, Math.max(...yTotals)],
nice: true,
});
const colorScale = scaleOrdinal<string, string>({
domain: keys,
range: colorRange,
});
// bounds
const xMax = width - margin.left - margin.right;
const yMax = height - margin.top - margin.bottom;
categoryScale.rangeRound([0, xMax]);
valueScale.range([yMax, 0]);
return width < 10 ? null : (
<div className={styles.container}>
<div className={styles.legend}>
<LegendOrdinal scale={colorScale} direction="row" itemMargin={itemMargin} labelAlign="center" />
</div>
<svg width={width} height={height}>
<Group top={margin.top} left={margin.left}>
<GridRows
scale={valueScale}
width={xMax}
height={yMax}
numTicks={numTicksValueAxis}
stroke={Color.tertiaryBackground}
strokeWidth={strokeWidth}
strokeDasharray={strokeDashArray}
/>
<GridColumns
scale={categoryScale}
height={yMax}
offset={categoryScale.bandwidth() / 2}
stroke={Color.tertiaryBackground}
strokeWidth={strokeWidth}
strokeDasharray={strokeDashArray}
/>
<BarStack<StackedBarData, string> data={data} keys={keys} x={getCategory} xScale={categoryScale} yScale={valueScale} color={colorScale}>
{(barStacks) =>
barStacks.map((barStack) =>
barStack.bars.map((bar) => (
<rect
className={styles.barStack}
key={`bar-stack-${barStack.index}-${bar.index}`}
x={bar.x}
y={bar.y}
height={bar.height}
width={bar.width / 2}
fill={bar.color}
onMouseLeave={() => {
tooltipTimeout = window.setTimeout(() => {
hideTooltip();
}, 300);
}}
onMouseMove={(event) => {
if (tooltipTimeout) clearTimeout(tooltipTimeout);
const tooltipPos = getTooltipPosition(event);
showTooltip({
tooltipData: bar,
tooltipLeft: tooltipPos.x,
tooltipTop: tooltipPos.y,
});
}}
/>
)),
)
}
</BarStack>
<Line
fill={Color.tertiaryBackground}
to={new Point({ x: 0, y: 0 })}
from={new Point({ x: 0, y: yMax })}
stroke={Color.tertiaryBackground}
strokeWidth={strokeWidth}
strokeDasharray={strokeDashArray}
/>
<AxisLeft
scale={valueScale}
top={5}
numTicks={numTicksValueAxis}
hideAxisLine
hideTicks
labelProps={{
fontSize: `${10 / 16}rem`,
}}
tickLabelProps={() => ({
fill: Color.label,
fontWeight: TICK_LABEL_FONT_WEIGHT,
textAnchor: "end",
})}
/>
</Group>
<AxisBottom
top={yMax + margin.top}
scale={categoryScale}
left={margin.left - categoryScale.bandwidth() / 4}
hideTicks
hideAxisLine
labelProps={{
fontSize: `${10 / 16}rem`,
}}
tickLabelProps={() => ({
fill: Color.label,
fontWeight: TICK_LABEL_FONT_WEIGHT,
textAnchor: "middle",
})}
/>
</svg>
{tooltipOpen && tooltipData ? (
<TooltipWrapper top={tooltipTop} left={tooltipLeft} header={tooltipData.key}>
{hideDataValueInTooltip ? null : (
<p>
{tooltipTopLabel} {tooltipData.bar.data[tooltipData.key]}
{displayPercentage ? "%" : ""}
</p>
)}
<p>
{tooltipBottomLabel} {getCategory(tooltipData.bar.data)}
</p>
</TooltipWrapper>
) : null}
</div>
);
},
);
export const StackedBarGraphHorizontal = withTooltip<StackedBarProps, TooltipData>(
({
data,
width,
height,
keys,
colorRange,
margin,
scalePadding = 0.3,
numTicksValueAxis = 6,
strokeWidth = 2.5,
strokeDashArray = "10,4",
itemMargin = "0 0 0 15px",
tooltipOpen,
tooltipLeft,
tooltipTop,
tooltipData,
hideTooltip,
showTooltip,
hideDataValueInTooltip,
tooltipBottomLabel = "",
tooltipTopLabel = "",
displayPercentage,
minWidth = 500,
}: StackedBarProps & WithTooltipProvidedProps<TooltipData>) => {
if (width < minWidth) {
width = minWidth;
}
const yTotals = data.reduce((allTotals, currCategory) => {
const yTotal = keys.reduce((categoryTotal, k) => {
categoryTotal += currCategory[k] as number;
return categoryTotal;
}, 0);
allTotals.push(yTotal);
return allTotals;
}, [] as number[]);
const TICK_LABEL_FONT_WEIGHT = 800;
// accessors
const getCategory = (d: StackedBarData) => d.category;
// scales
const valueScale = scaleLinear<number>({
domain: [0, Math.max(...yTotals)],
nice: true,
});
const categoryScale = scaleBand<string>({
domain: data.map(getCategory),
padding: scalePadding,
});
const colorScale = scaleOrdinal<string, string>({
domain: keys,
range: colorRange,
});
// bounds
const xMax = width - margin.left - margin.right;
const yMax = height - margin.top - margin.bottom;
categoryScale.rangeRound([yMax, 0]);
valueScale.range([0, xMax]);
return width < 10 ? null : (
<div className={styles.container}>
<div className={styles.legend}>
<LegendOrdinal scale={colorScale} direction="row" itemMargin={itemMargin} />
</div>
<svg width={width} height={height}>
<Group top={margin.top} left={margin.left}>
<GridRows
scale={categoryScale}
width={xMax}
height={yMax}
offset={categoryScale.bandwidth() / 2}
stroke={Color.tertiaryBackground}
strokeWidth={strokeWidth}
strokeDasharray={strokeDashArray}
/>
<GridColumns
scale={valueScale}
height={yMax}
numTicks={numTicksValueAxis}
stroke={Color.tertiaryBackground}
strokeWidth={strokeWidth}
strokeDasharray={strokeDashArray}
/>
<Line
fill={Color.tertiaryBackground}
to={new Point({ x: 0, y: 2 })}
from={new Point({ x: xMax, y: 2 })}
stroke={Color.tertiaryBackground}
strokeWidth={strokeWidth}
strokeDasharray={strokeDashArray}
/>
<BarStackHorizontal<StackedBarData, string> data={data} keys={keys} y={getCategory} xScale={valueScale} yScale={categoryScale} color={colorScale}>
{(barStacks) =>
barStacks.map((barStack) =>
barStack.bars.map((bar) => (
<rect
className={styles.barStack}
key={`bar-stack-${barStack.index}-${bar.index}`}
x={bar.x}
y={bar.y}
height={bar.height / 2}
width={bar.width}
fill={bar.color}
onMouseLeave={() => {
tooltipTimeout = window.setTimeout(() => {
hideTooltip();
}, 300);
}}
onMouseMove={(event) => {
if (tooltipTimeout) clearTimeout(tooltipTimeout);
const tooltipPos = getTooltipPosition(event);
showTooltip({
tooltipData: bar,
tooltipLeft: tooltipPos.x,
tooltipTop: tooltipPos.y,
});
}}
/>
)),
)
}
</BarStackHorizontal>
<AxisBottom
top={yMax}
scale={valueScale}
numTicks={numTicksValueAxis}
hideAxisLine
hideTicks
labelProps={{
fontSize: `${10 / 16}rem`,
}}
tickLabelProps={() => ({
fill: Color.label,
fontWeight: TICK_LABEL_FONT_WEIGHT,
textAnchor: "middle",
})}
/>
<AxisLeft
scale={categoryScale}
hideAxisLine
hideTicks
labelProps={{
fontSize: `${10 / 16}rem`,
}}
tickLabelProps={() => ({
fill: Color.label,
fontWeight: TICK_LABEL_FONT_WEIGHT,
textAnchor: "end",
})}
/>
</Group>
</svg>
{tooltipOpen && tooltipData ? (
<TooltipWrapper top={tooltipTop} left={tooltipLeft} header={tooltipData.key}>
{hideDataValueInTooltip ? null : (
<p>
{tooltipTopLabel} {tooltipData.bar.data[tooltipData.key]}
{displayPercentage ? "%" : ""}
</p>
)}
<p>
{tooltipBottomLabel} {getCategory(tooltipData.bar.data)}
</p>
</TooltipWrapper>
) : null}
</div>
);
},
);

View File

@ -0,0 +1,92 @@
.wrapper {
position: relative;
}
.line {
position: absolute;
height: 100%;
border-radius: calc(10rem / 16);
background-color: var(--secondary-accent);
z-index: -1;
}
.timelineSections {
width: 100%;
display: flex;
flex-direction: column;
justify-content: space-around;
gap: calc(20rem / 16);
}
.timelineSection {
width: 100%;
display: flex;
flex-direction: row;
justify-content: flex-end;
}
.time {
margin: 0;
text-align: right;
font-size: calc(30rem / 16);
font-weight: 700;
color: var(--secondary-accent);
word-wrap: break-word;
}
.outerCircle {
background-color: var(--secondary-accent);
box-shadow: calc(0rem / 16) calc(0rem / 16) calc(30rem / 16) var(--secondary-accent);
display: flex;
justify-content: center;
align-items: center;
}
.innerCircle {
background-color: var(--label);
display: none;
}
.text {
height: fit-content;
margin: 0;
padding: calc(15rem / 16);
border-radius: calc(10rem / 16);
font-size: calc(20rem / 16);
font-weight: 700;
color: var(--label);
border: calc(2rem / 16) solid var(--card-background);
background-color: var(--card-background);
word-wrap: break-word;
box-sizing: border-box;
}
.timelineSection:hover .time {
color: var(--secondary-accent-light);
}
.timelineSection:hover .innerCircle {
display: inline;
}
.timelineSection:hover .text {
border: calc(2rem / 16) solid var(--secondary-accent-light);
box-shadow: calc(0rem / 16) calc(0rem / 16) calc(20rem / 16) var(--secondary-accent);
}
.timelineSection .timeText {
display: none;
}
@media screen and (max-width: 900px) {
.timelineSection .time {
display: none;
}
.timelineSection .timeText {
display: block;
font-size: calc(26rem / 16);
color: var(--secondary-accent);
margin-bottom: calc(8rem / 16);
}
}

109
components/Timeline.tsx Normal file
View File

@ -0,0 +1,109 @@
import React from "react";
import styles from "./Timeline.module.css";
interface TimelineData {
time: string;
text: string;
}
interface TimelineProps {
data: TimelineData[];
/** Whether the time is transformed to uppercase. */
isTimeUppercase?: boolean;
/** Width of the middle timeline line, in pixels */
lineWidth?: number;
/** Width of the outer circles on the timeline, in pixels. */
outerCircleWidth?: number;
/** Width of the inner circles on the timeline, in pixels. */
innerCircleWidth?: number;
/** Width of text label, in pixels. */
textWidth?: number;
/** Distance between the time label AND the text label to middle line, in pixels. */
gap?: number;
className?: string;
}
export function Timeline({
data,
isTimeUppercase = true,
lineWidth = 5,
outerCircleWidth = 30,
innerCircleWidth = 15,
textWidth = 500,
gap = 50,
className,
}: TimelineProps) {
const largerMiddleElement = outerCircleWidth > lineWidth ? outerCircleWidth : lineWidth;
if (innerCircleWidth > outerCircleWidth) {
throw new Error(`<Timeline /> - innerCircleWidth (${innerCircleWidth}) is larger than outerCircleWidth (${outerCircleWidth})`);
}
return (
<div className={className ? `${className} ${styles.wrapper}` : `${styles.wrapper}`}>
<div
className={styles.line}
style={{
width: lineWidth,
right: textWidth + gap + largerMiddleElement / 2 - lineWidth / 2,
}}
/>
<div className={styles.timelineSections}>
{data.map((datum) => (
<TimelineSection
key={datum.time}
datum={datum}
isTimeUppercase={isTimeUppercase}
outerCircleWidth={outerCircleWidth}
innerCircleWidth={innerCircleWidth}
textWidth={textWidth}
gap={gap}
/>
))}
</div>
</div>
);
}
interface TimelineSectionProps {
datum: TimelineData;
isTimeUppercase: boolean;
outerCircleWidth: number;
innerCircleWidth: number;
textWidth: number;
gap: number;
}
function TimelineSection({ datum, isTimeUppercase, outerCircleWidth, innerCircleWidth, textWidth, gap }: TimelineSectionProps) {
return (
<div className={styles.timelineSection} style={{ gap: gap }}>
<div className={styles.time}>{isTimeUppercase ? datum.time.toUpperCase() : datum.time}</div>
<div
className={styles.outerCircle}
style={{
width: outerCircleWidth,
height: outerCircleWidth,
borderRadius: outerCircleWidth,
flex: `0 0 calc(${outerCircleWidth}rem / 16)`,
}}>
<div
className={styles.innerCircle}
style={{
width: innerCircleWidth,
height: innerCircleWidth,
borderRadius: innerCircleWidth,
}}
/>
</div>
<div
className={styles.text}
style={{
width: textWidth,
flex: `0 0 calc(${textWidth}rem / 16)`,
}}>
<div className={styles.timeText}>{datum.time}</div>
{datum.text}
</div>
</div>
);
}

View File

@ -0,0 +1,31 @@
.tooltip {
font-family: "Lexend", sans-serif;
top: 0;
left: 0;
position: absolute;
background-color: var(--label);
pointer-events: none;
padding: calc(10rem / 16);
border-radius: calc(10rem / 16);
font-size: calc(18rem / 16);
}
.header {
color: var(--primary-background);
margin: 0;
font-size: calc(16rem / 16);
font-weight: 700;
}
.body {
color: var(--primary-background);
margin-top: calc(5rem / 16);
font-size: calc(16rem / 16);
}
.body p {
color: var(--primary-background);
margin: 0;
padding: 0;
font-size: calc(16rem / 16) !important;
}

View File

@ -0,0 +1,67 @@
import localPoint from "@visx/event/lib/localPoint";
import { Point } from "@visx/point";
import { Tooltip } from "@visx/tooltip";
import React from "react";
import styles from "./TooltipWrapper.module.css";
type TooltipWrapperProps = {
top?: number;
left?: number;
className?: string;
header?: string;
children?: React.ReactNode;
};
// Finds the SVG Element which is the outmost from element (highest parent of element which is svg)
function getOutmostSVG(element: Element): SVGElement | undefined {
let rootSVG: HTMLElement | Element | null = element;
let current: HTMLElement | Element | null = element;
while (current) {
console.log(current);
if (current.tagName == "svg") {
rootSVG = current;
}
current = current.parentElement;
}
return rootSVG as SVGElement;
}
const TooltipWrapper = ({ top, left, className, header, children }: TooltipWrapperProps) => {
return (
<Tooltip top={top} left={left} className={`${styles.tooltip} ${className ?? ""}`} unstyled applyPositionStyle>
{header ? <span className={styles.header}>{header}</span> : null}
{children ? <div className={styles.body}>{children}</div> : null}
</Tooltip>
);
};
function getTooltipPosition(e: React.MouseEvent<SVGTextElement | SVGPathElement | SVGLineElement, MouseEvent>) {
// ownerSVGElement is given by visx docs but not recognized by typescript
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const eventElement = e.target.ownerSVGElement as Element;
const eventSvgCoords = localPoint(eventElement, e) as Point;
const rootSVG: SVGElement | undefined = getOutmostSVG(eventElement);
if (!rootSVG) {
console.error("Failed to find parent SVG for tooltip!");
return { x: 0, y: 0 };
}
const rootSVGLeft = rootSVG.getBoundingClientRect().left ?? 0;
const parentDivLeft = rootSVG.parentElement?.getBoundingClientRect().left ?? 0;
// visx localPoint does not account for the horizontal shift due to centering of the parent element,
// so manually add any shift from that
const alignmentOffset = rootSVGLeft - parentDivLeft;
return {
x: eventSvgCoords.x + alignmentOffset,
y: eventSvgCoords.y,
};
}
export { TooltipWrapper, getTooltipPosition };

View File

@ -0,0 +1,19 @@
.yellowWord:hover {
text-shadow: var(--chart-yellow-light) 0 0 calc(20rem / 16);
text-anchor: "middle";
cursor: default;
}
.yellowWord {
transition: text-shadow 0.25s ease-out;
}
.greenWord:hover {
text-shadow: var(--chart-green-light) 0 0 calc(20rem / 16);
text-anchor: "middle";
cursor: default;
}
.greenWord {
transition: text-shadow 0.25s ease-out;
}

240
components/WordCloud.tsx Normal file
View File

@ -0,0 +1,240 @@
"use client";
import { Color } from "@/utils/Color";
import { inDevEnvironment } from "@/utils/inDevEnviroment";
import { useIsMobile } from "@/utils/isMobile";
import { scaleLog } from "@visx/scale";
import { Text } from "@visx/text";
import { useTooltip, withTooltip } from "@visx/tooltip";
import { Wordcloud as VisxWordcloud } from "@visx/wordcloud";
import React from "react";
import { getTooltipPosition, TooltipWrapper } from "./TooltipWrapper";
import styles from "./WordCloud.module.css";
interface WordCloudProps {
data: Array<WordData>;
/** Width of the graph, in px */
width?: number;
/** The minimum width of the graph */
minWidth?: number;
/** Height of the graph, in px */
height?: number;
/** Minimum padding between words, in px */
wordPadding?: number;
/** Weight of the font of the words */
fontWeight?: number;
/** The desired font size of the smallest word on desktop, in px.*/
desktopMinFontSize?: number;
/** The desired font size of the smallest word on mobile, in px.*/
mobileMinFontSize?: number;
/** The desired font size of the largest word on desktop, in px. */
desktopMaxFontSize?: number;
/** The desired font size of the largest word on mobile, in px. */
mobileMaxFontSize?: number;
/** A random seed in the range [0, 1) used for placing the words, change this value to get an alternate placement of words */
randomSeed?: number;
/** Type of spiral used for rendering the words, either rectangular or archimedean */
spiral?: "rectangular" | "archimedean";
/** ClassName of the wrapper of the wordcloud */
className?: string;
/** Items that show up less frequently than this will be hidden */
minFrequency?: number;
/** Has a Background block or not */
background?: boolean;
}
interface WordData {
text: string;
value: number;
}
const TOOLTIP_HORIZONTAL_SHIFT_SCALER = 12.0;
export const WordCloud = withTooltip(
({
data,
width,
height,
wordPadding,
fontWeight,
desktopMinFontSize,
mobileMinFontSize,
desktopMaxFontSize,
mobileMaxFontSize,
randomSeed,
spiral,
className,
minWidth,
minFrequency,
background = false,
}: WordCloudProps) => {
const { tooltipData, tooltipLeft, tooltipTop, tooltipOpen, showTooltip, hideTooltip } = useTooltip<WordData>();
return (
<div className={className}>
<WordCloudWordsMemoized
width={width}
height={height}
data={minFrequency ? data.filter((x) => x.value >= minFrequency) : data}
wordPadding={wordPadding}
fontWeight={fontWeight}
desktopMinFontSize={desktopMinFontSize}
mobileMinFontSize={mobileMinFontSize}
desktopMaxFontSize={desktopMaxFontSize}
mobileMaxFontSize={mobileMaxFontSize}
showTooltip={(data, left, top) => {
showTooltip({
tooltipData: data,
tooltipLeft: left,
tooltipTop: top,
});
}}
hideTooltip={hideTooltip}
tooltipLeft={tooltipLeft}
tooltipTop={tooltipTop}
randomSeed={randomSeed}
spiral={spiral}
isMobile={useIsMobile()}
minWidth={minWidth}
background={background}
/>
{tooltipOpen && tooltipData ? (
<TooltipWrapper
// set this to random so it correctly updates with parent bounds
key={Math.random()}
top={tooltipTop}
left={tooltipLeft}
header={`${tooltipData.text} (${tooltipData.value})`}></TooltipWrapper>
) : null}
</div>
);
},
);
/** The internal wordcloud component that actually lays out the word needs to be separate from the tooltip to prevent extra rerendering. */
type WordCloudWordsProps = Omit<WordCloudProps, "className"> & {
showTooltip: (data: WordData, tooltipLeft: number, tooltipTop: number) => void;
hideTooltip: () => void;
// tooltipLeft and tooltipTop are used for preventing unnessary renders
tooltipLeft?: number;
tooltipTop?: number;
isMobile: boolean; // passing in isMobile as a prop so we can rerender if this changes
background?: boolean;
};
const WordCloudWords: React.FC<WordCloudWordsProps> = ({
data,
width = 1000,
minWidth = 500,
height = 500,
wordPadding = 20,
fontWeight = 400,
desktopMinFontSize = 15,
desktopMaxFontSize = 100,
mobileMinFontSize = 15,
mobileMaxFontSize = 60,
randomSeed = 0.5,
spiral = "rectangular",
showTooltip,
hideTooltip,
isMobile,
background = false,
}) => {
width = width < minWidth ? minWidth : width;
// In Block : Green
// Outside Block : Yellow
const wordColors = background ? [Color.chartGreenHeavy, Color.chartGreenLight] : [Color.chartYellowHeavy, Color.chartYellowLight];
const minFontSize = isMobile ? mobileMinFontSize : desktopMinFontSize;
const maxFontSize = isMobile ? mobileMaxFontSize : desktopMaxFontSize;
const maxVal = Math.max(...data.map((w) => w.value));
const minVal = Math.min(...data.map((w) => w.value));
const fontScale = scaleLog({
domain: [minVal, maxVal],
range: [minFontSize, maxFontSize],
});
const fontSizeSetter = (datum: WordData) => fontScale(datum.value);
const fixedValueGenerator = () => randomSeed;
return (
<VisxWordcloud
words={data}
width={width}
height={height}
fontSize={fontSizeSetter}
font="Inconsolata, monospace"
padding={wordPadding}
spiral={spiral}
rotate={0}
random={fixedValueGenerator}>
{(cloudWords) => {
if (
inDevEnvironment &&
cloudWords.length != 0 && // since on initial load the length is 0, but thats not an error
cloudWords.length != data.length
) {
console.error(
`Not all words rendered for wordcloud! (${
data.length - cloudWords.length
} words missing) Please try adjusting the min/max font size, the random seed, and the wordPadding`,
);
}
return cloudWords.map((word, index) => {
return (
<Text
key={`wordcloud-word-${word.text ?? ""}-${index}`}
fill={wordColors[index % wordColors.length]}
transform={`translate(${word.x ?? 0}, ${word.y ?? 0})`}
fontSize={word.size}
fontFamily={word.font}
fontWeight={fontWeight}
className={background ? styles.greenWord : styles.yellowWord}
textAnchor="middle"
onMouseMove={
((e: React.MouseEvent<SVGTextElement | SVGLineElement, MouseEvent>) => {
const tooltipPos = getTooltipPosition(e);
if (word.text) {
showTooltip(
{
text: word.text,
value: (cloudWords[index] as WordData).value,
},
tooltipPos.x - word.text.length * TOOLTIP_HORIZONTAL_SHIFT_SCALER,
tooltipPos.y,
);
}
}) as React.MouseEventHandler<SVGTextElement>
}
onMouseLeave={() => hideTooltip()}>
{word.text}
</Text>
);
});
}}
</VisxWordcloud>
);
};
const shouldNotRerender = (prevProps: WordCloudWordsProps, nextProps: WordCloudWordsProps) => {
if (
// if width changes, rerender, else don't rerender for a tooltip change
prevProps.width === nextProps.width &&
prevProps.isMobile === nextProps.isMobile &&
prevProps.background === nextProps.background &&
(prevProps.tooltipLeft !== nextProps.tooltipLeft ||
prevProps.tooltipTop !== nextProps.tooltipTop ||
nextProps.tooltipLeft === undefined ||
nextProps.tooltipTop === undefined)
) {
return true; // do not re-render
}
return false; // will re-render
};
const WordCloudWordsMemoized = React.memo(WordCloudWords, shouldNotRerender);

844
data/academics.ts Normal file
View File

@ -0,0 +1,844 @@
export const A1 = [
{ category: "On time", value: 111 },
{ category: "Earlier", value: 10 },
{ category: "Later", value: 10 },
];
export const A2 = [
{ category: "Comm / Humanities", value: 62 },
{ category: "Pure Science", value: 27 },
{ category: "Applied Science", value: 9 },
{ category: "Social Science", value: 39 },
];
export const A3 = [
{ text: "CS 452", value: 7 },
{ text: "CS 246E", value: 3 },
{ text: "CS 480", value: 7 },
{ text: "CS 488", value: 6 },
{ text: "CS 349", value: 5 },
{ text: "CS 486", value: 13 },
{ text: "CS 241", value: 9 },
{ text: "CS 341", value: 5 },
{ text: "CS 343", value: 5 },
{ text: "CS 240", value: 2 },
{ text: "CS 350", value: 7 },
{ text: "CS 456", value: 4 },
{ text: "CS 458", value: 2 },
{ text: "CS 454", value: 3 },
{ text: "CS 246", value: 9 },
{ text: "CS 145", value: 1 },
{ text: "CS 492", value: 2 },
{ text: "CS 146", value: 4 },
{ text: "CS 251", value: 1 },
{ text: "CS 135", value: 4 },
{ text: "CS 449", value: 4 },
{ text: "CS 241E", value: 1 },
{ text: "CS 442", value: 3 },
{ text: "CS 451", value: 5 },
{ text: "CS 346", value: 3 },
{ text: "CS 245E", value: 1 },
{ text: "CS 446", value: 2 },
{ text: "CS 370", value: 2 },
{ text: "CS 466", value: 1 },
{ text: "CS 450", value: 1 },
{ text: "CS 479", value: 1 },
{ text: "CS 482", value: 1 },
{ text: "CS 360", value: 1 },
{ text: "CS 245", value: 1 },
{ text: "CS 489", value: 1 },
{ text: "CS 444", value: 1 },
];
export const A4 = [
{ text: "CS 245", value: 27 },
{ text: "CS 245E", value: 3 },
{ text: "CS 247", value: 1 },
{ text: "CS 490", value: 3 },
{ text: "CS 343", value: 3 },
{ text: "CS 246", value: 7 },
{ text: "CS 350", value: 10 },
{ text: "CS 492", value: 2 },
{ text: "CS 251", value: 12 },
{ text: "CS 348", value: 10 },
{ text: "CS 370", value: 2 },
{ text: "CS 480", value: 3 },
{ text: "CS 135", value: 3 },
{ text: "CS 241", value: 6 },
{ text: "CS 451", value: 2 },
{ text: "CS 456", value: 8 },
{ text: "CS 240", value: 5 },
{ text: "CS 446", value: 2 },
{ text: "CS 360", value: 2 },
{ text: "CS 479", value: 1 },
{ text: "CS 485", value: 1 },
{ text: "CS 349", value: 1 },
{ text: "CS 458", value: 1 },
{ text: "CS 486", value: 1 },
{ text: "CS 448", value: 4 },
{ text: "CS 484", value: 1 },
{ text: "CS 351", value: 1 },
{ text: "CS 341", value: 1 },
];
export const A5 = [
{ text: "MUSIC 140", value: 6 },
{ text: "ENGL 336", value: 1 },
{ text: "SE 212", value: 1 },
{ text: "CLAS 104", value: 1 },
{ text: "MATH 135", value: 3 },
{ text: "CHINA 101", value: 1 },
{ text: "PMATH 810", value: 1 },
{ text: "CHEM 220", value: 1 },
{ text: "MATH 239", value: 4 },
{ text: "MUSIC 116", value: 1 },
{ text: "LS 229", value: 1 },
{ text: "EASIA 336R", value: 1 },
{ text: "BUS 433W", value: 1 },
{ text: "MUSIC 246", value: 10 },
{ text: "ECON 371", value: 2 },
{ text: "ERS 102", value: 1 },
{ text: "PHIL 255", value: 1 },
{ text: "MATH 147", value: 1 },
{ text: "SCI 238", value: 3 },
{ text: "CO 487", value: 7 },
{ text: "EASIA 302R", value: 1 },
{ text: "ECON 372", value: 1 },
{ text: "SPCOM 223", value: 1 },
{ text: "CO 380", value: 1 },
{ text: "GER 101", value: 1 },
{ text: "JAPAN 101R", value: 3 },
{ text: "ENGL 335", value: 1 },
{ text: "KOR 202R", value: 1 },
{ text: "ENGL 306A", value: 2 },
{ text: "ECON 206", value: 1 },
{ text: "ECON 212", value: 4 },
{ text: "GEOG 306", value: 1 },
{ text: "GEOG 101", value: 1 },
{ text: "PSCI 384", value: 1 },
{ text: "DAC 204", value: 1 },
{ text: "ENGL 109", value: 1 },
{ text: "ENGL 251", value: 1 },
{ text: "JAPAN 101", value: 2 },
{ text: "BIOL 469", value: 1 },
{ text: "ENGL 378", value: 1 },
{ text: "RUSS 102", value: 1 },
{ text: "BET 300", value: 2 },
{ text: "ENGL 484", value: 1 },
{ text: "MATH 235", value: 2 },
{ text: "COMM 400", value: 2 },
{ text: "CO 342", value: 3 },
{ text: "FINE 130", value: 1 },
{ text: "INTEG 220", value: 1 },
{ text: "KOREA 101", value: 1 },
{ text: "ENGL 460B", value: 1 },
{ text: "MATH 145", value: 2 },
{ text: "BET 201", value: 1 },
{ text: "STAT 341", value: 1 },
{ text: "PHIL 256", value: 1 },
{ text: "CHEM 464", value: 1 },
{ text: "BET 350", value: 1 },
{ text: "SCI 207", value: 3 },
{ text: "BUS 479", value: 1 },
{ text: "PHIL 145", value: 1 },
{ text: "CO 250", value: 1 },
{ text: "SCI 206", value: 2 },
{ text: "BU 488", value: 1 },
{ text: "PSYCH 256R", value: 1 },
{ text: "PMATH 450", value: 1 },
{ text: "FINE 319", value: 1 },
{ text: "ENGL 292", value: 1 },
{ text: "ECE 454", value: 1 },
{ text: "CO 330", value: 1 },
{ text: "PLAN 300", value: 1 },
{ text: "EMLS 102R", value: 1 },
{ text: "ECON 101", value: 2 },
{ text: "BU 430", value: 1 },
{ text: "CS 486", value: 1 },
{ text: "AHS 100", value: 1 },
{ text: "BET 430", value: 1 },
{ text: "AFM 321", value: 1 },
{ text: "BET 320", value: 1 },
{ text: "MUSIC 260", value: 1 },
{ text: "PSYCH 227", value: 1 },
{ text: "RS 228", value: 1 },
];
export const A6 = [
{ text: "STAT 231", value: 17 },
{ text: "ECE 124", value: 2 },
{ text: "ECE 192", value: 1 },
{ text: "BU 354W", value: 1 },
{ text: "EARTH 121", value: 2 },
{ text: "STAT 332", value: 1 },
{ text: "MATH 239", value: 5 },
{ text: "SPCOM 100", value: 4 },
{ text: "PHYS 121", value: 2 },
{ text: "ENGL 109", value: 6 },
{ text: "CLAS 104", value: 1 },
{ text: "BUS 481W", value: 1 },
{ text: "PD 11", value: 3 },
{ text: "PHYS 122", value: 4 },
{ text: "EMLS 103R", value: 1 },
{ text: "MATH 138", value: 2 },
{ text: "STAT 341", value: 1 },
{ text: "MATH 135", value: 1 },
{ text: "ENGL 119", value: 4 },
{ text: "PHYS 111", value: 1 },
{ text: "SPCOM 225", value: 8 },
{ text: "ENGL 108D", value: 3 },
{ text: "PHIL 101", value: 1 },
{ text: "SOC 101", value: 1 },
{ text: "ENGL 378", value: 2 },
{ text: "SCI 238", value: 1 },
{ text: "ECON 102", value: 5 },
{ text: "ECON 361", value: 1 },
{ text: "HRM 200", value: 1 },
{ text: "STAT 230", value: 1 },
{ text: "ECON 101", value: 2 },
{ text: "REC 100", value: 1 },
{ text: "SPCOM 223", value: 4 },
{ text: "PSYCH 101", value: 1 },
{ text: "AFM 101", value: 3 },
{ text: "PHIL 145", value: 1 },
{ text: "PSYCH 207", value: 1 },
{ text: "AFM 131", value: 2 },
{ text: "CHEM 220", value: 1 },
{ text: "PSYCH 339", value: 1 },
{ text: "MATH 136", value: 3 },
{ text: "PD 1", value: 1 },
{ text: "ECON 201", value: 1 },
{ text: "CO 487", value: 1 },
{ text: "STAT 340", value: 1 },
{ text: "MATH 237", value: 1 },
{ text: "BU 111", value: 1 },
{ text: "AFM 372", value: 1 },
{ text: "PHIL 215", value: 1 },
{ text: "FINE 257", value: 1 },
{ text: "EMLS 101R", value: 1 },
{ text: "BIOL 309", value: 1 },
{ text: "ECON 206", value: 1 },
];
export const A7 = [
{ text: "CS 452", value: 6 },
{ text: "MATH 147", value: 1 },
{ text: "ECE 124", value: 1 },
{ text: "CS 480", value: 8 },
{ text: "CS 341", value: 7 },
{ text: "CS 466", value: 7 },
{ text: "PMATH 810", value: 1 },
{ text: "CS 246", value: 5 },
{ text: "MATH 145", value: 6 },
{ text: "CS 343", value: 9 },
{ text: "MATH 239", value: 12 },
{ text: "PMATH 351", value: 2 },
{ text: "CS 350", value: 9 },
{ text: "CO 250", value: 3 },
{ text: "CS 488", value: 6 },
{ text: "CO 487", value: 2 },
{ text: "CS 444", value: 2 },
{ text: "MATH 135", value: 3 },
{ text: "CS 454", value: 1 },
{ text: "STAT 240", value: 2 },
{ text: "MATH 138", value: 2 },
{ text: "CO 255", value: 2 },
{ text: "CS 448", value: 2 },
{ text: "MATH 245", value: 1 },
{ text: "STAT 241", value: 1 },
{ text: "MATH 235", value: 1 },
{ text: "CS 485", value: 2 },
{ text: "CS 458", value: 1 },
{ text: "PMATH 347", value: 1 },
{ text: "CS 486", value: 1 },
{ text: "ECE 106", value: 1 },
{ text: "STAT 443", value: 1 },
{ text: "CO 331", value: 1 },
{ text: "STAT 333", value: 1 },
{ text: "PMATH 453", value: 1 },
{ text: "CS 456", value: 1 },
{ text: "ECON 101", value: 1 },
{ text: "CS 240", value: 1 },
{ text: "CS 484", value: 1 },
{ text: "MATH 247", value: 1 },
{ text: "CS 476", value: 1 },
{ text: "AFM 131", value: 1 },
{ text: "STAT 341", value: 1 },
{ text: "CS 360", value: 1 },
{ text: "STAT 231", value: 1 },
{ text: "CS 146", value: 1 },
];
export const A8 = [
{ text: "MUSIC 140", value: 7 },
{ text: "CS 145", value: 1 },
{ text: "ENGL 109", value: 1 },
{ text: "MUSIC 240", value: 1 },
{ text: "CLAS 104", value: 19 },
{ text: "MATH 137", value: 1 },
{ text: "HEALTH 105", value: 1 },
{ text: "CS 370", value: 2 },
{ text: "CHEM 120", value: 1 },
{ text: "CS 480", value: 1 },
{ text: "SOC 101", value: 1 },
{ text: "EASIA 336R", value: 1 },
{ text: "CS 135", value: 4 },
{ text: "MUSIC 246", value: 3 },
{ text: "CS 449", value: 5 },
{ text: "ENGL 108P", value: 1 },
{ text: "PMATH 340", value: 1 },
{ text: "SPAN 101", value: 1 },
{ text: "SCI 206", value: 1 },
{ text: "ENGL 119", value: 1 },
{ text: "ECON 101", value: 11 },
{ text: "GEOG 101", value: 1 },
{ text: "ECON 102", value: 1 },
{ text: "PSYCH 101", value: 3 },
{ text: "CLAS 202", value: 4 },
{ text: "BET 100", value: 1 },
{ text: "ECE 351", value: 1 },
{ text: "SPCOM 100", value: 3 },
{ text: "KOREA 101", value: 1 },
{ text: "CS 497", value: 1 },
{ text: "CS 490", value: 1 },
{ text: "CS 348", value: 2 },
{ text: "JAPAN 101R", value: 1 },
{ text: "CS 451", value: 1 },
{ text: "FR 192B", value: 1 },
{ text: "ERS 270", value: 1 },
{ text: "CS 446", value: 3 },
{ text: "KIN 121", value: 1 },
{ text: "BET 201", value: 1 },
{ text: "STAT 332", value: 1 },
{ text: "STAT 230", value: 1 },
{ text: "PSYCH 207", value: 1 },
{ text: "BUS 479", value: 1 },
{ text: "ENGL 108A", value: 1 },
{ text: "PHIL 202", value: 1 },
{ text: "EARTH 123", value: 1 },
{ text: "MATH 117", value: 1 },
{ text: "REC 280", value: 2 },
{ text: "COMM 200", value: 1 },
{ text: "CS 486", value: 1 },
{ text: "PHYS 111", value: 1 },
{ text: "LS 496", value: 1 },
{ text: "ECON 322", value: 1 },
{ text: "PSYCH 232", value: 1 },
{ text: "MATH 146", value: 1 },
{ text: "SCI 201", value: 1 },
{ text: "ECE 495", value: 1 },
{ text: "HIST 236", value: 1 },
{ text: "MUSIC 101", value: 1 },
{ text: "SPCOM 223", value: 1 },
{ text: "ASL 101", value: 1 },
{ text: "MATH 135", value: 1 },
{ text: "ENGL 335", value: 1 },
{ text: "SCI 207", value: 1 },
{ text: "AFM 101", value: 2 },
{ text: "HRM 200", value: 1 },
];
export const A9 = [
{ text: "CS 349", value: 1 },
{ text: "MATH 147", value: 2 },
{ text: "ECE 124", value: 2 },
{ text: "ECE 192", value: 1 },
{ text: "REC 100", value: 1 },
{ text: "CS 490", value: 1 },
{ text: "PMATH 340", value: 1 },
{ text: "STAT 332", value: 1 },
{ text: "STAT 341", value: 3 },
{ text: "ECON 201", value: 2 },
{ text: "ECON 101", value: 5 },
{ text: "CS 451", value: 2 },
{ text: "PHYS 121", value: 2 },
{ text: "CO 486", value: 1 },
{ text: "CO 250", value: 2 },
{ text: "CO 487", value: 2 },
{ text: "PD 10", value: 4 },
{ text: "ECON 102", value: 1 },
{ text: "CS 486", value: 2 },
{ text: "CS 480", value: 4 },
{ text: "CS 370", value: 3 },
{ text: "CS 343", value: 2 },
{ text: "PD 11", value: 2 },
{ text: "CS 456", value: 4 },
{ text: "PD 1", value: 2 },
{ text: "EARTH 121", value: 1 },
{ text: "ENGL 119", value: 1 },
{ text: "ENGL 108D", value: 2 },
{ text: "SPCOM 225", value: 2 },
{ text: "MATH 136", value: 1 },
{ text: "CS 446", value: 2 },
{ text: "SOC 101", value: 1 },
{ text: "CS 454", value: 1 },
{ text: "MATH 239", value: 1 },
{ text: "CS 448", value: 6 },
{ text: "HRM 200", value: 1 },
{ text: "ECE 351", value: 1 },
{ text: "BIOL 239", value: 1 },
{ text: "ECON 371", value: 1 },
{ text: "MATH 237", value: 2 },
{ text: "CS 245", value: 1 },
{ text: "CS 348", value: 5 },
{ text: "STV 202", value: 1 },
{ text: "MATH 236", value: 1 },
{ text: "AFM 101", value: 2 },
{ text: "ENGL 101B", value: 1 },
{ text: "CS 445", value: 2 },
{ text: "FINE 130", value: 1 },
{ text: "PSCI 150", value: 1 },
{ text: "CS 458", value: 1 },
{ text: "STAT 230", value: 2 },
{ text: "PSYCH 339", value: 1 },
{ text: "BUS 422", value: 1 },
{ text: "CO 367", value: 1 },
{ text: "CHINA 102R", value: 1 },
{ text: "MUSIC 246", value: 1 },
{ text: "CS 241E", value: 1 },
{ text: "PD 8", value: 1 },
{ text: "STAT 340", value: 1 },
{ text: "PHYS 122", value: 1 },
{ text: "MATH 235", value: 1 },
{ text: "CS 484", value: 1 },
{ text: "PSYCH 207", value: 1 },
{ text: "MUSIC 140", value: 1 },
{ text: "FINE 257", value: 1 },
{ text: "MTHEL 131", value: 1 },
{ text: "AHS 105", value: 1 },
{ text: "FR 192A", value: 1 },
];
export const A10 = [
{ text: "CS 452", value: 4 },
{ text: "CS 246E", value: 4 },
{ text: "CS 341", value: 24 },
{ text: "CS 246", value: 31 },
{ text: "PMATH 453", value: 1 },
{ text: "CS 348", value: 3 },
{ text: "CS 458", value: 1 },
{ text: "CS 350", value: 9 },
{ text: "CS 146", value: 1 },
{ text: "CS 135", value: 1 },
{ text: "CHINA 120", value: 1 },
{ text: "CS 486", value: 2 },
{ text: "AFM 121", value: 1 },
{ text: "CS 454", value: 4 },
{ text: "CS 240", value: 3 },
{ text: "MATH 135", value: 2 },
{ text: "CS 346", value: 1 },
{ text: "ENGL 251", value: 1 },
{ text: "CS 480", value: 5 },
{ text: "CS 451", value: 2 },
{ text: "CS 456", value: 4 },
{ text: "CS 446", value: 1 },
{ text: "CS 488", value: 4 },
{ text: "SDS 331R", value: 1 },
{ text: "CHEM 494", value: 1 },
{ text: "CS 240E", value: 1 },
{ text: "CS 449", value: 2 },
{ text: "ECON 371", value: 1 },
{ text: "CS 444", value: 1 },
{ text: "PHIL 110B", value: 1 },
{ text: "PHIL 324", value: 1 },
];
export const A11 = [
{ text: "STAT 231", value: 2 },
{ text: "ECE 192", value: 2 },
{ text: "CS 245", value: 10 },
{ text: "CS 490", value: 3 },
{ text: "GEOG 306", value: 1 },
{ text: "MUSIC 140", value: 3 },
{ text: "CLAS 104", value: 5 },
{ text: "ECON 101", value: 4 },
{ text: "ENGL 109", value: 1 },
{ text: "BU 121", value: 1 },
{ text: "PMATH 441", value: 1 },
{ text: "PSYCH 101", value: 2 },
{ text: "SPCOM 223", value: 2 },
{ text: "PD 5", value: 1 },
{ text: "PD 1", value: 5 },
{ text: "EARTH 121", value: 1 },
{ text: "PD 10", value: 5 },
{ text: "ENGL 210F", value: 1 },
{ text: "HRM 200", value: 2 },
{ text: "PHYS 111", value: 1 },
{ text: "PHIL 215", value: 1 },
{ text: "ECON 102", value: 3 },
{ text: "ENGL 119", value: 2 },
{ text: "SPCOMM 223", value: 1 },
{ text: "PD 4", value: 1 },
{ text: "CS 446", value: 2 },
{ text: "SOC 101", value: 1 },
{ text: "CS 360", value: 1 },
{ text: "SCI 238", value: 1 },
{ text: "CS 479", value: 1 },
{ text: "ANTH 100", value: 2 },
{ text: "STAT 431", value: 1 },
{ text: "CS 348", value: 3 },
{ text: "CS 448", value: 2 },
{ text: "PD 11", value: 6 },
{ text: "STV 202", value: 1 },
{ text: "PSYCH 207", value: 1 },
{ text: "SPCOM 100", value: 1 },
{ text: "ENGL 101B", value: 1 },
{ text: "CS 445", value: 1 },
{ text: "CS 485", value: 1 },
{ text: "SMF 101", value: 1 },
{ text: "AFM 131", value: 2 },
{ text: "CS 251", value: 2 },
{ text: "ENGL 108D", value: 1 },
{ text: "PSYCH 339", value: 1 },
{ text: "CS 241", value: 1 },
{ text: "PHYS 225", value: 1 },
{ text: "ECON 201", value: 1 },
{ text: "PD 8", value: 1 },
{ text: "CO 250", value: 1 },
{ text: "CS 135", value: 2 },
{ text: "CLAS 202", value: 1 },
{ text: "STAT 340", value: 1 },
{ text: "AFM 101", value: 1 },
{ text: "CS 350", value: 1 },
{ text: "CS 451", value: 1 },
{ text: "CS 492", value: 2 },
{ text: "CLAS 101", value: 1 },
{ text: "FINE 130", value: 1 },
{ text: "MUSIC 240", value: 1 },
{ text: "CO 351", value: 1 },
{ text: "CS 370", value: 1 },
{ text: "MGMT 244", value: 1 },
{ text: "AFM 102", value: 1 },
{ text: "FINE 257", value: 1 },
{ text: "MATH 235", value: 1 },
];
export const A12 = [
{ category: "Yes", value: 48 },
{ category: "No", value: 83 },
];
export const A12i = [
{ category: "CS145", values: [0, 0, 4, 6, 11] },
{ category: "CS146", values: [0, 0, 3, 3, 16] },
{ category: "MATH145", values: [2, 1, 4, 5, 13] },
{ category: "MATH146", values: [1, 1, 1, 4, 13] },
{ category: "MATH147", values: [1, 1, 4, 5, 13] },
{ category: "MATH148", values: [0, 1, 2, 4, 3] },
{ category: "MATH245", values: [0, 1, 6, 5, 1] },
{ category: "MATH247", values: [0, 0, 2, 3, 4] },
{ category: "MATH249", values: [0, 0, 3, 4, 8] },
{ category: "CS240E", values: [0, 0, 1, 2, 1] },
{ category: "CS241E", values: [2, 0, 1, 3, 9] },
{ category: "CS245E", values: [4, 1, 2, 3, 3] },
{ category: "CS246E", values: [1, 1, 1, 2, 11] },
{ category: "STAT240", values: [2, 3, 1, 3, 2] },
{ category: "STAT241", values: [0, 1, 5, 2, 0] },
];
export const A12iKeys = ["1", "2", "3", "4", "5"];
export const A13 = [
{ category: "No", value: 94 },
{ category: "Yes", value: 39 },
];
export const A13i = [
{ category: "SE", value: 10 },
{ category: "CS/BBA", value: 3 },
{ category: "MATH", value: 15 },
{ category: "CFM", value: 4 },
{ category: "MATH/BBA", value: 1 },
{ category: "MATH/CPA", value: 1 },
{ category: "KI", value: 1 },
{ category: "CA COOP", value: 1 },
{ category: "MECH ENG", value: 1 },
{ category: "MED SCI", value: 1 },
{ category: "ENV", value: 1 },
];
export const A13ii = [
{ category: "1B", value: 4 },
{ category: "2A", value: 19 },
{ category: "2B", value: 6 },
{ category: "3A", value: 6 },
{ category: "3B", value: 3 },
];
export const A13iii = [
{ category: "Flexible schedule", value: 6 },
{ category: "More interest", value: 14 },
{ category: "Better job prospects", value: 11 },
{ category: "Avoid course(s)", value: 2 },
{ category: "Flexible courses", value: 4 },
{ category: "Graduate early", value: 1 },
{ category: "No ECE courses", value: 1 },
];
export const A14 = [
{ text: "Brad Lushman", value: 3 },
{ text: "Pascal Poupart", value: 4 },
{ text: "Simon Wood", value: 5 },
{ text: "Lesley Istead", value: 8 },
{ text: "Martin Pei", value: 1 },
{ text: "Dan Wolczuk", value: 5 },
{ text: "Yaoliang Yu", value: 1 },
{ text: "Alice Gao", value: 21 },
{ text: "Jordan Hamilton", value: 5 },
{ text: "Jeff Avery", value: 6 },
{ text: "Ali Abedi", value: 1 },
{ text: "Blake Madill", value: 3 },
{ text: "Daivd Jao", value: 1 },
{ text: "Alfred Menezes", value: 4 },
{ text: "David Mckinnon", value: 1 },
{ text: "Jill Smith", value: 1 },
{ text: "David Jao", value: 2 },
{ text: "Ian Payne", value: 1 },
{ text: "Ondrej Lhotak", value: 1 },
{ text: "Gregor Richards", value: 1 },
{ text: "Jingjing Huo", value: 1 },
{ text: "Troy Vasiga", value: 1 },
{ text: "Eddie Dupont", value: 2 },
{ text: "Edith Law", value: 1 },
{ text: "Onyeka Ezeh", value: 1 },
{ text: "Nomair Naeem", value: 4 },
{ text: "Wayne Chang", value: 2 },
{ text: "Carmen Bruni", value: 2 },
{ text: "Peter Buhr", value: 1 },
{ text: "Gregory Rice", value: 2 },
{ text: "Buhr Peter", value: 1 },
{ text: "Craig Fortier", value: 1 },
{ text: "Nick Ray", value: 1 },
{ text: "Sonny Lee", value: 1 },
{ text: "Joe West", value: 1 },
{ text: "Keith Delaney", value: 1 },
{ text: "Dan Holtby", value: 1 },
{ text: "Martin Karsten", value: 2 },
{ text: "Richard Dlin", value: 1 },
{ text: "Owen Woody", value: 1 },
{ text: "Meng Xu", value: 1 },
{ text: "Jerry Wang", value: 1 },
{ text: "Richard Epp", value: 1 },
{ text: "Yi Shen", value: 1 },
{ text: "No One", value: 1 },
{ text: "David McKinnon", value: 1 },
{ text: "Laura Gray", value: 1 },
{ text: "Erik Hintz", value: 1 },
];
export const A15 = [
{ category: "1A", value: 5 },
{ category: "1B", value: 8 },
{ category: "2A", value: 45 },
{ category: "2B", value: 31 },
{ category: "3A", value: 12 },
{ category: "3B", value: 13 },
{ category: "4A", value: 8 },
{ category: "4B", value: 3 },
{ category: "5A", value: 2 },
];
export const A16 = [
{ category: "1A", value: 15 },
{ category: "1B", value: 4 },
{ category: "2A", value: 2 },
{ category: "2B", value: 3 },
{ category: "3A", value: 7 },
{ category: "3B", value: 15 },
{ category: "4A", value: 20 },
{ category: "4B", value: 50 },
{ category: "5A", value: 6 },
{ category: "5B", value: 3 },
];
export const A17 = [
{ category: "1A", "0-30": 0, "30-60": 1, "60-70": 3, "70-80": 12, "80-90": 52, "90-95": 25, "95-100": 7 },
{ category: "1B", "0-30": 0, "30-60": 1, "60-70": 6.2, "70-80": 19.6, "80-90": 41.3, "90-95": 23.7, "95-100": 8.2 },
{ category: "2A", "0-30": 0, "30-60": 3.06, "60-70": 9.18, "70-80": 19.39, "80-90": 43.88, "90-95": 22.45, "95-100": 2.04 },
{ category: "2B", "0-30": 0, "30-60": 1.03, "60-70": 4.12, "70-80": 12.37, "80-90": 32.99, "90-95": 34.03, "95-100": 15.46 },
{ category: "3A", "0-30": 0, "30-60": 0, "60-70": 5.1, "70-80": 8.16, "80-90": 34.69, "90-95": 37.76, "95-100": 14.29 },
{ category: "3B", "0-30": 0, "30-60": 0, "60-70": 2.08, "70-80": 13.54, "80-90": 39.59, "90-95": 30.21, "95-100": 14.58 },
{ category: "4A", "0-30": 0, "30-60": 0, "60-70": 2.2, "70-80": 16.48, "80-90": 38.47, "90-95": 36.26, "95-100": 6.59 },
{ category: "4B", "0-30": 1.61, "30-60": 0, "60-70": 6.45, "70-80": 16.13, "80-90": 35.48, "90-95": 30.65, "95-100": 9.68 },
{ category: "5A", "0-30": 0, "30-60": 0, "60-70": 0, "70-80": 0, "80-90": 0, "90-95": 85.71, "95-100": 14.29 },
{ category: "5B", "0-30": 0, "30-60": 0, "60-70": 0, "70-80": 50, "80-90": 50, "90-95": 0, "95-100": 0 },
];
export const A17Keys = ["0-30", "30-60", "60-70", "70-80", "80-90", "90-95", "95-100"];
export const A18 = [
{ category: "0-30", value: 0 },
{ category: "30-60", value: 0 },
{ category: "60-70", value: 1 },
{ category: "70-80", value: 22 },
{ category: "80-90", value: 46 },
{ category: "90-95", value: 29 },
{ category: "95-100", value: 3 },
];
export const A19 = [
{ category: "0-30", value: 0 },
{ category: "30-60", value: 0 },
{ category: "60-70", value: 2 },
{ category: "70-80", value: 18 },
{ category: "80-90", value: 45 },
{ category: "90-95", value: 25 },
{ category: "95-100", value: 7 },
];
export const A20 = [
{ category: "No", value: 72 },
{ category: "Yes", value: 55 },
];
export const A20i = [
{ text: "Pure Mathematics", value: 2 },
{ text: "Combinatorics and Optimization", value: 3 },
{ text: "Business", value: 2 },
{ text: "HCI", value: 1 },
{ text: "Diploma in Creative Writing", value: 1 },
{ text: "Japanese language diploma I", value: 1 },
{ text: "Statistics", value: 1 },
{ text: "Bioinformatics", value: 1 },
{ text: "Marketing", value: 1 },
{ text: "Pure Math", value: 1 },
{ text: "Artificial Inteligence", value: 1 },
{ text: "Financial management", value: 1 },
];
export const A20ii = [
{ text: "Combinatorics & Optimization", value: 16 },
{ text: "Computational Mathematics", value: 5 },
{ text: "Statistics", value: 5 },
{ text: "Pure Mathematics", value: 2 },
{ text: "Legal Studies", value: 1 },
{ text: "Economics", value: 4 },
{ text: "Political Science", value: 1 },
{ text: "Business", value: 1 },
{ text: "Entrepreneurship", value: 3 },
{ text: "Economic Theory", value: 1 },
{ text: "English Language & Literature", value: 1 },
{ text: "Fine Arts", value: 1 },
{ text: "French", value: 1 },
];
export const A20iii = [
{ text: "Business", value: 2 },
{ text: "Artificial Intelligence", value: 4 },
{ text: "Human-Computer Interaction", value: 3 },
{ text: "Data Science", value: 4 },
{ text: "Software Engineering", value: 1 },
{ text: "Strategic Management (WLU)", value: 1 },
];
export const A20iv = [
"Feel like expanding my field of knowledge",
"Dropped out of CS/BBA with all the BU courses needed for specialization",
"Other areas of mathematics was more interesting than computer science for me",
"I like UI and designing things",
"Interesting courses, and barely any extra courses",
"General interest + depth requirement",
"Interest + I had most of the courses anyway",
"I was interested in Political Science.",
"Minor to help me differentiate my skills from just programmer, Software Engineering Specialization to drill down those key topics.",
"Statistics major is easy to complete.",
"I was interested in seeing if there was any further interest in these fields.",
"Just wanted to do anything I could to stand out for PM applications and read that maybe this could help? Honestly looking back now, I don't think it helped that much, but what was smart was that the options/concentrations I chose naturally aligned with my strengths as a student. So it was almost like a lucky accident I chose to specialize because it helped me look at the right courses that I would perform better in and boost my GPA to something half decent.",
"Interesting courses for CO, then CM had a very high overlap with the CS and CO courses I took.",
"I enjoyed CO 250 and wanted to take more CO courses",
"Relevance to career goals",
"I love math, and was already 2 terms away from both majors when I switched into CS",
"personal interest + matching skillset + future for career",
];
export const A21 = [
{ category: "0", value: 67 },
{ category: "1", value: 16 },
{ category: "2", value: 15 },
{ category: "3", value: 5 },
{ category: "4", value: 4 },
{ category: "5", value: 4 },
{ category: "6", value: 2 },
];
export const A22 = [
{ category: "0", value: 98 },
{ category: "1", value: 11 },
{ category: "2", value: 5 },
{ category: "3", value: 4 },
];
export const A23 = [
{ category: "0", value: 73 },
{ category: "1", value: 18 },
{ category: "2", value: 9 },
{ category: "3", value: 8 },
{ category: "4", value: 3 },
{ category: "5", value: 1 },
{ category: "6", value: 1 },
];
export const A24 = [
{ category: "No", value: 115 },
{ category: "Yes", value: 11 },
];
export const A24i = [
{ category: "4B", value: 2 },
{ category: "4A", value: 8 },
{ category: "2A", value: 1 },
];
export const A24ii = [
"UNIL, Lausanne, Switzerland",
"Universidad Carlos III de Madrid, Madrid, Spain",
"TU Delft, Delft, Netherlands",
"Technical University of Delft, Delft, Netherlands",
"NTU, Singapore, Singapore",
"EPFL, Lausanne, Switzerland",
"University of Waterloo, Rome, Italy",
"National University of Singapore, Singapore, Singapore",
"City University of Hong Kong, Hong Kong, China",
"NUS, Singapore, Singapore",
];
export const A24iii = [
"Expensive",
"Traveling",
"Being the only asian",
"Making friends",
"First few days getting settled",
"Money",
"Being independent",
"Long distance relationship",
];
export const A24iv = [
"The music events",
"Trips to Prague",
"Travelling",
"Bali trip",
"Friends",
"Going out with my friends",
"Travel with awesome folks around Southeast Asia!",
];
export const A25 = [
{ text: "Village 1", value: 40 },
{ text: "UW Place", value: 20 },
{ text: "Columbia Lake Village", value: 16 },
{ text: "St. Jerome's University College", value: 4 },
{ text: "Ron Eydt Village", value: 12 },
{ text: "Mackenzie King Village", value: 11 },
{ text: "Renison University College", value: 1 },
{ text: "Lived off campus", value: 8 },
{ text: "Claudette Millar Hall", value: 4 },
{ text: "Lived off campus, at home", value: 6 },
{ text: "Conrad Grebel University College", value: 3 },
{ text: "United College (formerly St. Paul's University College)", value: 1 },
];
export const A26 = [
{ category: "No", value: 103 },
{ category: "Yes", value: 26 },
];

View File

@ -0,0 +1,94 @@
export const E1 = [
{ category: "High School", value: 96 },
{ category: "Online Courses", value: 38 },
{ category: "Coding Competitions", value: 48 },
{ category: "Internship", value: 22 },
{ category: "Personal Website", value: 23 },
{ category: "Hackathons", value: 35 },
{ category: "LeetCode", value: 16 },
];
export const E2 = [
{ category: "0", value: 3 },
{ category: "1", value: 1 },
{ category: "2", value: 9 },
{ category: "3", value: 11 },
{ category: "4", value: 15 },
{ category: "5", value: 22 },
{ category: "6", value: 16 },
{ category: "7", value: 15 },
{ category: "8", value: 13 },
{ category: "9", value: 4 },
{ category: "10", value: 20 },
];
export const E3 = [
{ text: "Python", value: 67 },
{ text: "C++", value: 20 },
{ text: "Kotlin", value: 4 },
{ text: "Go", value: 8 },
{ text: "Java", value: 5 },
{ text: "Racket", value: 2 },
{ text: "JavaScript", value: 5 },
{ text: "Rust", value: 6 },
{ text: "Swift", value: 2 },
{ text: "TypeScript", value: 7 },
{ text: "C", value: 2 },
{ text: "Haskell", value: 1 },
{ text: "C#", value: 2 },
];
export const E4 = [
{ text: "VSCode", value: 93 },
{ text: "JetBrains", value: 16 },
{ text: "Vim", value: 8 },
{ text: "Sublime Text", value: 5 },
{ text: "Emacs", value: 4 },
{ text: "Notepad++", value: 2 },
{ text: "Neovim", value: 1 },
{ text: "TextEdit", value: 1 },
{ text: "Notepad", value: 1 },
];
export const E5 = [
{ category: "Windows", value: 62 },
{ category: "MacOS", value: 81 },
{ category: "Linux", value: 30 },
];
export const E6 = [
{ category: "Hard", value: 13 },
{ category: "Medium", value: 68 },
{ category: "Easy", value: 17 },
{ category: "None", value: 33 },
];
export const E7 = [
{ category: "0", value: 25 },
{ category: "1", value: 18 },
{ category: "2", value: 29 },
{ category: "3", value: 22 },
{ category: "4", value: 12 },
{ category: "5", value: 4 },
{ category: "6", value: 1 },
{ category: "7", value: 0 },
{ category: "8", value: 5 },
{ category: "9", value: 0 },
{ category: "10", value: 4 },
];
export const E8 = [
{ category: "0", value: 29 },
{ category: "1", value: 21 },
{ category: "2", value: 21 },
{ category: "3", value: 22 },
{ category: "4", value: 7 },
{ category: "5", value: 5 },
{ category: "6", value: 4 },
{ category: "7", value: 6 },
{ category: "9", value: 1 },
{ category: "10", value: 4 },
{ category: "11", value: 1 },
{ category: "18", value: 1 },
{ category: "23", value: 1 },
];

32
data/contributors.ts Normal file
View File

@ -0,0 +1,32 @@
export const communityReps = [
{ name: "Kim Guo", link: "https://www.linkedin.com/in/kbrqin/" },
{ name: "Imane Yacoubi", link: "https://www.linkedin.com/in/iyacoubi" },
{ name: "Ashnoor Randhawa", link: "https://www.linkedin.com/in/ashnoor-kaur/" },
{ name: "Mayank Mehra", link: "https://www.linkedin.com/in/mayank808/" },
{ name: "Katherine Liu", link: "https://www.linkedin.com/in/katherine-liu-59b30324a/" },
{ name: "Ivy Lei", link: "https://www.linkedin.com/in/ivy-lei/" },
{ name: "Kevin Cui", link: "https://www.linkedin.com/in/kevincui1" },
];
export const designers = [
{ name: "Kim Guo", link: "https://www.linkedin.com/in/kbrqin/" },
{ name: "Cadey Chen", link: "https://www.linkedin.com/in/cadey-chen/" },
{ name: "Ashlyn Wu", link: "https://www.linkedin.com/in/ashlynwu/" },
{ name: "Roni Wu", link: "https://www.linkedin.com/in/roni-wu-908900140/" },
{ name: "Jessica Chan", link: "https://www.linkedin.com/in/jessica-r-chan/" },
{ name: "Linda Wang", link: "https://www.linkedin.com/in/linda-y-wang/" },
{ name: "Kelly Qu", link: "https://www.linkedin.com/in/kellyqu/" },
{ name: "Anny Wei", link: "https://www.linkedin.com/in/annyzwei/" },
{ name: "Lucy Qi", link: "https://www.linkedin.com/in/lucyqqi/" },
{ name: "Lila Hoang", link: "https://www.linkedin.com/in/lila-hoang-a13851263/" },
{ name: "Hailey Chan", link: "https://www.linkedin.com/in/chan-hailey/" },
];
export const CPWebDevs = [
{ name: "Alexander Liao", link: "https://www.linkedin.com/in/alexander-liao/" },
{ name: "Kushal Goel", link: "https://www.linkedin.com/in/kushal-goel/" },
{ name: "Cathie Yan", link: "https://www.linkedin.com/in/cathie-yan/" },
{ name: "Ryan Zhou", link: "https://www.linkedin.com/in/ryan-zhou-498b94285/" },
{ name: "Emily Huang", link: "https://www.linkedin.com/in/emilyhuxng/" },
{ name: "Franklin Ramirez", link: "https://www.linkedin.com/in/franklin-ramirez611/" },
];

671
data/coop.ts Normal file
View File

@ -0,0 +1,671 @@
export const C1 = [
{ category: "Yes", value: 128 },
{ category: "No", value: 7 },
];
export const C2 = [
{ text: "Palo Alto", value: 1 },
{ text: "Calgary", value: 2 },
{ text: "Boston", value: 1 },
{ text: "Tokyo", value: 1 },
{ text: "Atlanta", value: 1 },
{ text: "Chicago", value: 1 },
{ text: "Kitchener-Waterloo", value: 10 },
{ text: "Lausanne", value: 1 },
{ text: "San Francisco", value: 14 },
{ text: "New York City", value: 30 },
{ text: "Los Angeles", value: 1 },
{ text: "Seattle", value: 7 },
{ text: "Toronto", value: 22 },
{ text: "Menlo Park", value: 2 },
{ text: "Vancouver", value: 11 },
{ text: "San Mateo", value: 3 },
{ text: "Montreal", value: 3 },
{ text: "Richmond", value: 1 },
{ text: "Remote", value: 1 },
{ text: "Sunnyvale", value: 1 },
{ text: "Bay Area", value: 1 },
];
export const C3 = [
{ category: "Yes", value: 23 },
{ category: "No", value: 100 },
];
export const C4 = [
{ category: "Yes", value: 8 },
{ category: "No", value: 115 },
];
export const C5 = [
{ category: "0", value: 86 },
{ category: "1", value: 17 },
{ category: "2", value: 3 },
{ category: "3", value: 1 },
{ category: "4", value: 0 },
{ category: "5+", value: 3 },
];
export const C6i = [
[
{ text: "Intelerad Medical Systems", value: 1 },
{ text: "Formlabs", value: 1 },
{ text: "A Thinking Ape", value: 1 },
{ text: "Prizm Media", value: 1 },
{ text: "TD Bank", value: 2 },
{ text: "Stealth Monitoring", value: 1 },
{ text: "Solace", value: 1 },
{ text: "EPASS", value: 1 },
{ text: "Kooltra", value: 1 },
{ text: "Rich Media", value: 1 },
{ text: "ADP", value: 2 },
{ text: "Super", value: 1 },
{ text: "Opslevel", value: 1 },
{ text: "Ritual", value: 1 },
{ text: "Veeva Systems", value: 1 },
{ text: "IBM", value: 1 },
{ text: "Uber ATG", value: 2 },
{ text: "Deloitte", value: 1 },
{ text: "Raven Telemetry", value: 1 },
{ text: "MappelIn Inc", value: 1 },
{ text: "Toronto Transit Commission", value: 1 },
{ text: "Ericsson", value: 1 },
{ text: "Touchdown Education", value: 1 },
{ text: "Titanium Agency", value: 1 },
{ text: "Imagine Communications", value: 1 },
{ text: "Shaw Communications", value: 1 },
{ text: "CPP Investments", value: 1 },
{ text: "Purolator", value: 1 },
{ text: "Osellus Mobile", value: 3 },
{ text: "The Co-operators General Insurance Company", value: 1 },
{ text: "Maple Leaf Foods", value: 1 },
{ text: "Pheedloop", value: 1 },
{ text: "Deep Trekker", value: 1 },
{ text: "VL Omni", value: 1 },
{ text: "AWS", value: 1 },
{ text: "CIBC", value: 2 },
{ text: "Ai startup", value: 1 },
{ text: "Manulife Financial", value: 3 },
{ text: "ATS", value: 1 },
{ text: "WorkMarket", value: 1 },
{ text: "Government of New Brunswick", value: 1 },
{ text: "Ontario MGCS", value: 1 },
{ text: "Wish", value: 4 },
{ text: "Qualcomm", value: 1 },
{ text: "Hubdoc", value: 2 },
{ text: "Gore Mutual Insurance", value: 2 },
{ text: "Watonomous", value: 1 },
{ text: "Celestica", value: 1 },
{ text: "Transport Canada", value: 1 },
{ text: "Scotiabank", value: 1 },
{ text: "Finlogik", value: 1 },
{ text: "Bunz", value: 1 },
{ text: "Agriculture and Agri-Food Canada", value: 1 },
{ text: "Canadian Solar Inc.", value: 1 },
{ text: "Terradatum", value: 1 },
{ text: "Honeywell", value: 1 },
{ text: "RBC", value: 1 },
{ text: "Conrad School of Entrepreneurship", value: 1 },
{ text: "University of Waterloo", value: 2 },
{ text: "Instacart", value: 1 },
{ text: "Infor", value: 1 },
{ text: "Aterica Digital Health", value: 1 },
{ text: "Genesys", value: 1 },
{ text: "Opentext", value: 1 },
{ text: "Plooto", value: 1 },
{ text: "NVIDIA", value: 1 },
{ text: "Statistics Canada", value: 1 },
{ text: "Flashfood Inc.", value: 1 },
{ text: "Shopedge Software", value: 1 },
{ text: "Macdonald Dettwiler and Associates", value: 1 },
{ text: "The Home Depot", value: 1 },
{ text: "BlackBerry", value: 1 },
{ text: "Connected", value: 1 },
{ text: "eSentire", value: 1 },
{ text: "Shopper Army", value: 1 },
{ text: "Amazon", value: 1 },
{ text: "Emailgistics", value: 1 },
{ text: "Shaw Communications Inc.", value: 1 },
{ text: "KGS Research", value: 1 },
{ text: "Google", value: 1 },
],
[
{ text: "Untether AI", value: 1 },
{ text: "University of Waterloo", value: 2 },
{ text: "Shopify", value: 3 },
{ text: "Wish", value: 7 },
{ text: "RBC", value: 4 },
{ text: "AMD", value: 1 },
{ text: "Thomson Reuters", value: 2 },
{ text: "Huawei", value: 3 },
{ text: "Blackberry", value: 2 },
{ text: "Allstate Canada", value: 1 },
{ text: "Hubdoc", value: 1 },
{ text: "Lazer Technologies", value: 1 },
{ text: "Bronte College", value: 1 },
{ text: "Intelex Technologies", value: 1 },
{ text: "Microsoft", value: 1 },
{ text: "Uber", value: 2 },
{ text: "Snaptravel", value: 1 },
{ text: "Hockeystick", value: 1 },
{ text: "DigitalEd", value: 1 },
{ text: "Canada Revenue Agency", value: 1 },
{ text: "Kaleidescape", value: 1 },
{ text: "Tesla", value: 1 },
{ text: "Titanium Agency", value: 2 },
{ text: "Enlighted Inc", value: 1 },
{ text: "Squarepoint Capital", value: 1 },
{ text: "Curvegrid", value: 1 },
{ text: "PointClickCare", value: 1 },
{ text: "ContextLogic", value: 2 },
{ text: "Statistics Canada", value: 1 },
{ text: "RewardOps", value: 1 },
{ text: "Deloitte", value: 1 },
{ text: "Secret Mission Software", value: 1 },
{ text: "IBM", value: 1 },
{ text: "Evidence Partners", value: 1 },
{ text: "Remitbee", value: 1 },
{ text: "Wealthsimple", value: 1 },
{ text: "Onsemi", value: 1 },
{ text: "Cognitive Systems", value: 1 },
{ text: "TD Securities", value: 1 },
{ text: "Doppl Inc", value: 1 },
{ text: "Traderev", value: 1 },
{ text: "NPX", value: 1 },
{ text: "ROSS intelligence", value: 1 },
{ text: "Co-operators", value: 3 },
{ text: "Plangrid", value: 1 },
{ text: "Via Rail", value: 1 },
{ text: "Bluescape", value: 1 },
{ text: "Bloomberg", value: 1 },
{ text: "Kinaxis ", value: 1 },
{ text: "RadComm Systems", value: 1 },
{ text: "Terradatum", value: 1 },
{ text: "Honeywell", value: 1 },
{ text: "Tealbook", value: 1 },
{ text: "Loblaws", value: 1 },
{ text: "SAP", value: 1 },
{ text: "TradeRev", value: 1 },
{ text: "Wayfair", value: 1 },
{ text: "HyAlto", value: 1 },
{ text: "Ontario Institute of Cancer Research", value: 1 },
{ text: "Government of Canada", value: 1 },
{ text: "hyperPad", value: 1 },
{ text: "Manulife", value: 1 },
{ text: "Beeshop Solutions", value: 1 },
{ text: "ODAIA", value: 1 },
{ text: "Designware ", value: 1 },
{ text: "Kooltra", value: 1 },
{ text: "Zenreach", value: 1 },
{ text: "hitplay", value: 1 },
{ text: "Zenreach", value: 1 },
{ text: "TunnelBear", value: 1 },
{ text: "ThoughtWire", value: 1 },
{ text: "KGS Research", value: 1 },
{ text: "Social Capital", value: 1 },
],
[
{ text: "", value: 43 },
{ text: "Google", value: 3 },
{ text: "FreeBSD Foundation", value: 1 },
{ text: "Shopify", value: 3 },
{ text: "FISPAN", value: 1 },
{ text: "Ecobee", value: 2 },
{ text: "AMD", value: 1 },
{ text: "University of Alberta", value: 1 },
{ text: "Paphus Solutions", value: 1 },
{ text: "Achievers", value: 3 },
{ text: "Allstate Canada", value: 1 },
{ text: "Wish", value: 7 },
{ text: "Hubhead", value: 1 },
{ text: "Teleport", value: 1 },
{ text: "Fundserv", value: 1 },
{ text: "Intelex Technologies", value: 1 },
{ text: "Side Effects", value: 1 },
{ text: "Adeptmind", value: 1 },
{ text: "Lumafield", value: 1 },
{ text: "Hockeystick", value: 2 },
{ text: "Roscience", value: 1 },
{ text: "Miovision Technologies", value: 1 },
{ text: "Ford", value: 3 },
{ text: "OMERS", value: 1 },
{ text: "TQ Tezos", value: 1 },
{ text: "Titanium Agency", value: 2 },
{ text: "Yext", value: 1 },
{ text: "AWS", value: 1 },
{ text: "Coinbase", value: 1 },
{ text: "Geotab", value: 1 },
{ text: "FairVentures Lab", value: 1 },
{ text: "Setter/Thumbtack", value: 1 },
{ text: "DarwinAI", value: 1 },
{ text: "Citadel Securities", value: 1 },
{ text: "University of Waterloo", value: 1 },
{ text: "Tryosoft", value: 1 },
{ text: "Huawei", value: 2 },
{ text: "Big Blue Bubble", value: 1 },
{ text: "National Bank of Canada", value: 1 },
{ text: "Pronti AI", value: 2 },
{ text: "Nuvalence", value: 1 },
{ text: "Paravision", value: 1 },
{ text: "hyperPad", value: 1 },
{ text: "Intact", value: 1 },
{ text: "Heymarket", value: 1 },
{ text: "Kinaxis", value: 1 },
{ text: "ContextLogic", value: 2 },
{ text: "RadComm Systems", value: 1 },
{ text: "MDA (MacDonald Dettwiler and Associates)", value: 1 },
{ text: "Textnow", value: 1 },
{ text: "Faire", value: 1 },
{ text: "Miovision", value: 1 },
{ text: "SAP", value: 1 },
{ text: "Amazon", value: 1 },
{ text: "Seatgeek", value: 1 },
{ text: "Geminare", value: 1 },
{ text: "Bespoke Metrics", value: 1 },
{ text: "Christie Digital Systems", value: 1 },
{ text: "Coursera", value: 1 },
{ text: "BDO", value: 1 },
{ text: "PointClickCare", value: 1 },
{ text: "Xero", value: 1 },
{ text: "Untether.Ai", value: 1 },
{ text: "Betstamp", value: 1 },
{ text: "TD Asset Management", value: 1 },
{ text: "KPMG LLP", value: 1 },
{ text: "Clearco", value: 1 },
{ text: "Hudson River Trading", value: 1 },
{ text: "BinSentry", value: 1 },
{ text: "Kooltra", value: 1 },
{ text: "WorkMarket", value: 1 },
{ text: "Farm Business Consultants", value: 1 },
{ text: "Manulife", value: 1 },
],
[
{ text: "", value: 44 },
{ text: "Facebook", value: 4 },
{ text: "NVIDIA", value: 4 },
{ text: "Bloomberg", value: 1 },
{ text: "PagerDuty", value: 2 },
{ text: "Vector Institute", value: 1 },
{ text: "SSENSE", value: 1 },
{ text: "Salesforce", value: 2 },
{ text: "Lifion by ADP", value: 1 },
{ text: "Google", value: 4 },
{ text: "Meta", value: 2 },
{ text: "IBM Extreme Blue", value: 1 },
{ text: "Coursera", value: 1 },
{ text: "Wish", value: 5 },
{ text: "Adeptmind", value: 1 },
{ text: "Roblox", value: 1 },
{ text: "Tangam Systems", value: 1 },
{ text: "Arctic Wolf Networks", value: 1 },
{ text: "University of Waterloo", value: 3 },
{ text: "GTS", value: 1 },
{ text: "Thomson Reuters", value: 2 },
{ text: "Tesla", value: 1 },
{ text: "KPMG", value: 1 },
{ text: "Autodesk Research", value: 1 },
{ text: "Splunk", value: 3 },
{ text: "Dropbox", value: 1 },
{ text: "Polychain", value: 1 },
{ text: "Alloy", value: 1 },
{ text: "Snowflake", value: 1 },
{ text: "Amazon", value: 3 },
{ text: "Snaptravel", value: 1 },
{ text: "Shopify", value: 1 },
{ text: "Hudson River Trading", value: 1 },
{ text: "SAP", value: 2 },
{ text: "LCBO", value: 1 },
{ text: "Huawei", value: 1 },
{ text: "Equitable Life", value: 1 },
{ text: "Uber", value: 1 },
{ text: "Scale AI", value: 1 },
{ text: "Department of National Defense", value: 1 },
{ text: "Certik", value: 1 },
{ text: "Faire", value: 2 },
{ text: "Replicant", value: 1 },
{ text: "Playstation", value: 1 },
{ text: "Squarepoint Capital", value: 1 },
{ text: "Yugabyte", value: 1 },
{ text: "Twitch", value: 1 },
{ text: "Citadel", value: 1 },
{ text: "Cisco Meraki", value: 1 },
{ text: "Vertica", value: 1 },
{ text: "Nuvalence", value: 1 },
{ text: "Snap", value: 1 },
{ text: "Boosted.AI", value: 1 },
{ text: "Achievers", value: 3 },
{ text: "DarwinAi ", value: 1 },
{ text: "Morgan Stanley", value: 1 },
{ text: "Siemens", value: 1 },
{ text: "Boston Consulting Group", value: 1 },
{ text: "Wonolo", value: 1 },
{ text: "Ramp", value: 1 },
{ text: "Wattpad", value: 1 },
{ text: "Baseline", value: 1 },
{ text: "Clearbanc", value: 1 },
{ text: "Atolio Inc.", value: 1 },
{ text: "Riot Games", value: 1 },
],
[
{ text: "SBX Robotics", value: 1 },
{ text: "", value: 47 },
{ text: "Mattermost", value: 1 },
{ text: "Databricks", value: 2 },
{ text: "Twitter", value: 1 },
{ text: "Snowflake", value: 4 },
{ text: "University of Waterloo", value: 2 },
{ text: "Datadog", value: 1 },
{ text: "Meta", value: 13 },
{ text: "Lyft", value: 1 },
{ text: "Citadel Securities", value: 1 },
{ text: "Robinhood", value: 2 },
{ text: "Wish", value: 1 },
{ text: "Waabi", value: 1 },
{ text: "Adeptmind", value: 1 },
{ text: "Amazon", value: 5 },
{ text: "American Express", value: 1 },
{ text: "Microsoft", value: 1 },
{ text: "Vercada", value: 1 },
{ text: "GTS", value: 2 },
{ text: "Rippling", value: 2 },
{ text: "Citadel", value: 2 },
{ text: "Jane Street", value: 1 },
{ text: "Arctic Wolf", value: 1 },
{ text: "Whatnot", value: 1 },
{ text: "Gem Software", value: 1 },
{ text: "NVIDIA", value: 3 },
{ text: "Shopify", value: 1 },
{ text: "Jane Street Capital", value: 1 },
{ text: "Uber", value: 1 },
{ text: "Squarepoint Capital", value: 1 },
{ text: "Akuna Capital", value: 1 },
{ text: "RideCo", value: 1 },
{ text: "Zynga", value: 1 },
{ text: "Replicant", value: 1 },
{ text: "ZeMind Studios", value: 1 },
{ text: "Stripe", value: 1 },
{ text: "Doordash", value: 1 },
{ text: "Yugabyte", value: 1 },
{ text: "Lifion by ADP", value: 2 },
{ text: "Scale AI", value: 1 },
{ text: "Snap", value: 1 },
{ text: "Huawei", value: 1 },
{ text: "Emmetros Inc", value: 1 },
{ text: "HRT", value: 1 },
{ text: "Noom", value: 1 },
{ text: "Bitgo", value: 1 },
{ text: "Apple", value: 1 },
{ text: "1Password", value: 1 },
{ text: "Opal", value: 1 },
{ text: "Faire", value: 1 },
{ text: "Enzuzo Inc.", value: 1 },
{ text: "OANDA", value: 1 },
{ text: "Shaw Communications", value: 1 },
{ text: "LinkedIn", value: 1 },
{ text: "Instabase", value: 1 },
],
[
{ text: "", value: 75 },
{ text: "Rippling", value: 2 },
{ text: "Meta", value: 5 },
{ text: "IMC Trading", value: 1 },
{ text: "Jane Street", value: 2 },
{ text: "Snap", value: 2 },
{ text: "Ecole Polytechnique Federale de Lausanne", value: 1 },
{ text: "ASAPP", value: 1 },
{ text: "Datadog", value: 3 },
{ text: "Stripe", value: 2 },
{ text: "Gem", value: 1 },
{ text: "Bloomberg", value: 4 },
{ text: "IMC", value: 1 },
{ text: "Amazon", value: 6 },
{ text: "Uber", value: 1 },
{ text: "Waabi", value: 2 },
{ text: "Contrary", value: 1 },
{ text: "Verkada", value: 1 },
{ text: "Eden Industries", value: 1 },
{ text: "Shopify", value: 1 },
{ text: "University of Waterloo", value: 2 },
{ text: "Capital One", value: 1 },
{ text: "Ecobee", value: 1 },
{ text: "Octant Blo", value: 1 },
{ text: "RideCo", value: 1 },
{ text: "Noom", value: 1 },
{ text: "Tactic Studios", value: 1 },
{ text: "Akuna Capital", value: 2 },
{ text: "Citadel", value: 1 },
{ text: "Robinhood", value: 1 },
{ text: "Google", value: 1 },
{ text: "Faire", value: 1 },
{ text: "Databricks", value: 1 },
{ text: "Peritus.ai", value: 1 },
{ text: "Cruise", value: 1 },
{ text: "LinkedIn", value: 1 },
{ text: "CIBC", value: 1 },
{ text: "Splunk", value: 1 },
{ text: "Riot Games", value: 1 },
{ text: "Intuit", value: 1 },
{ text: "Level", value: 1 },
],
];
export const C6ii = {
xValues: ["1", "2", "3", "4", "5", "6"],
lines: [
{ label: "Kitchener/Waterloo", yValues: [21.4, 11.2, 6, 5.3, 6.1, 6.3] },
{ label: "GTA/Toronto", yValues: [49.1, 29.9, 12.1, 9.6, 7.9, 8.8] },
{ label: "Remote", yValues: [8, 34.6, 65.5, 71.9, 41.2, 26.3] },
{ label: "USA", yValues: [3.6, 11.2, 7.8, 8.8, 37.7, 53.8] },
{ label: "Other", yValues: [17.9, 13.1, 8.6, 4.4, 7.1, 4.8] },
],
};
export const C6iii = [
[
{ text: "Backend", value: 21 },
{ text: "QA", value: 5 },
{ text: "IT", value: 1 },
{ text: "ISA", value: 1 },
{ text: "QA", value: 5 },
{ text: "Testing", value: 2 },
{ text: "Full-Stack", value: 36 },
{ text: "DevOps", value: 4 },
{ text: "Social Media Specialist", value: 1 },
{ text: "Frontend", value: 13 },
{ text: "Quant", value: 1 },
{ text: "Mobile", value: 4 },
{ text: "RPA Development", value: 1 },
{ text: "SEO", value: 1 },
{ text: "Toolset Developer", value: 1 },
{ text: "Quality Engineering", value: 1 },
{ text: "Firmware", value: 1 },
{ text: "Research", value: 1 },
{ text: "BETS Program", value: 1 },
{ text: "QA Engineering", value: 2 },
{ text: "Survey Programmer", value: 1 },
{ text: "Research Assistant", value: 1 },
],
[
{ text: "Backend", value: 28 },
{ text: "Mobile", value: 3 },
{ text: "Kernel Development", value: 2 },
{ text: "ISA", value: 1 },
{ text: "Firmware Tooling", value: 1 },
{ text: "Data Engineering", value: 4 },
{ text: "Full-Stack", value: 35 },
{ text: "QA Automation", value: 1 },
{ text: "Frontend", value: 11 },
{ text: "Research Assistant", value: 2 },
{ text: "Venture Capital", value: 1 },
{ text: "Data Science", value: 9 },
{ text: "Machine Learning Researcher", value: 1 },
{ text: "Unrelated", value: 1 },
{ text: "Automated Testing Engineer", value: 1 },
{ text: "Survey Programmer", value: 1 },
],
[
{ text: "Backend", value: 37 },
{ text: "Mobile", value: 6 },
{ text: "Software Developer", value: 1 },
{ text: "Systems Development", value: 1 },
{ text: "DevOps", value: 3 },
{ text: "Data Engineering", value: 1 },
{ text: "Full-Stack", value: 30 },
{ text: "Production Engineer", value: 1 },
{ text: "Blockchain", value: 1 },
{ text: "Frontend", value: 5 },
{ text: "Research", value: 2 },
{ text: "Firmware", value: 1 },
{ text: "BI Programmer", value: 1 },
{ text: "Research Assistant", value: 1 },
{ text: "Designer", value: 1 },
{ text: "Data Science", value: 4 },
{ text: "Framework Development", value: 1 },
{ text: "Data Engineer", value: 1 },
{ text: "AI", value: 1 },
{ text: "C++ Developer", value: 1 },
],
[
{ text: "Backend", value: 31 },
{ text: "Mobile", value: 6 },
{ text: "Databases", value: 1 },
{ text: "Systems Development", value: 1 },
{ text: "Product Management", value: 1 },
{ text: "Research", value: 1 },
{ text: "Full-Stack", value: 28 },
{ text: "Cyber Security", value: 2 },
{ text: "Firmware Tooling", value: 1 },
{ text: "Frontend", value: 7 },
{ text: "Software Consulting", value: 1 },
{ text: "Quantitative Development", value: 1 },
{ text: "Game Development", value: 1 },
{ text: "Research Assistant", value: 2 },
{ text: "Venture Capital", value: 1 },
{ text: "Data Science", value: 6 },
{ text: "Infrastructure", value: 1 },
{ text: "Compiler Development", value: 1 },
{ text: "Machine Learning Engineer", value: 1 },
{ text: "UX/UI Designer", value: 1 },
{ text: "Data Engineer", value: 1 },
{ text: "Firmware", value: 1 },
{ text: "C++ Developer", value: 1 },
],
[
{ text: "Backend", value: 34 },
{ text: "Mobile", value: 4 },
{ text: "Databases", value: 2 },
{ text: "Technical Program Management", value: 1 },
{ text: "Product Management", value: 3 },
{ text: "Research", value: 3 },
{ text: "Full-Stack", value: 21 },
{ text: "Systems", value: 1 },
{ text: "Tools and Compilers", value: 1 },
{ text: "Frontend", value: 2 },
{ text: "Low-level C++", value: 1 },
{ text: "Quantitative Development", value: 2 },
{ text: "Machine Learning", value: 1 },
{ text: "Game Development", value: 1 },
{ text: "Research Assistant", value: 1 },
{ text: "ISA", value: 1 },
{ text: "Data Science", value: 9 },
{ text: "Infrastructure", value: 1 },
{ text: "Graphics", value: 1 },
{ text: "Machine Learning Researcher", value: 1 },
{ text: "UX/UI Designer", value: 1 },
{ text: "Data Engineer", value: 1 },
{ text: "C++ Developer", value: 1 },
],
[
{ text: "Backend", value: 24 },
{ text: "Mobile", value: 1 },
{ text: "Research Assistant", value: 2 },
{ text: "Data Engineer", value: 2 },
{ text: "Product Management", value: 1 },
{ text: "DevX", value: 1 },
{ text: "Full-Stack", value: 12 },
{ text: "Systems", value: 1 },
{ text: "Quant Dev", value: 2 },
{ text: "Frontend", value: 4 },
{ text: "Venture Capital", value: 1 },
{ text: "Machine Learning Research", value: 1 },
{ text: "DevOps", value: 2 },
{ text: "Game Development", value: 2 },
{ text: "Research", value: 1 },
{ text: "ISA", value: 1 },
{ text: "Data Science", value: 3 },
{ text: "Trading Engine", value: 1 },
{ text: "Software Developer", value: 1 },
{ text: "Machine Learning Engineer", value: 1 },
{ text: "UX/UI Designer", value: 1 },
],
];
export const C6iv = [
{ category: "1", min: 15, firstQuartile: 18, median: 20, thirdQuartile: 23.3, max: 30, outliers: [0, 2.5, 5, 40, 41, 56.6] },
{ category: "2", min: 12, firstQuartile: 22, median: 26, thirdQuartile: 34, max: 53, outliers: [55.6, 60, 60, 60, 64, 66.6, 70] },
{ category: "3", min: 15, firstQuartile: 26, median: 30, thirdQuartile: 42, max: 66, outliers: [0, 66.5, 70, 75, 127.4, 130] },
{ category: "4", min: 17, firstQuartile: 28, median: 35, thirdQuartile: 50, max: 80, outliers: [100, 140] },
{ category: "5", min: 20, firstQuartile: 37, median: 49, thirdQuartile: 67, max: 112, outliers: [126, 139, 160] },
{ category: "6", min: 17, firstQuartile: 32.5, median: 50, thirdQuartile: 77.3, max: 134, outliers: [] },
];
export const C6v = [
{ category: "1", min: 0, firstQuartile: 0, median: 0, thirdQuartile: 200, max: 6000, outliers: [15894, 25000] },
{ category: "2", min: 0, firstQuartile: 0, median: 0, thirdQuartile: 2000, max: 15894, outliers: [25000, 93000] },
{ category: "3", min: 0, firstQuartile: 0, median: 0, thirdQuartile: 2000, max: 7000, outliers: [10000, 13000, 35000] },
{ category: "4", min: 0, firstQuartile: 0, median: 0, thirdQuartile: 2450, max: 6160, outliers: [10000, 10000, 10000, 10000, 10000, 13000, 20000] },
{ category: "5", min: 0, firstQuartile: 0, median: 5000, thirdQuartile: 10205.2, max: 26000, outliers: [30000, 47000, 52000] },
{ category: "6", min: 0, firstQuartile: 0, median: 6000, thirdQuartile: 10000, max: 23587, outliers: [35000, 35000] },
];
export const C6viKey = ["Outstanding", "Excellent", "Very Good", "Good"];
export const C6vi = [
{ category: "1", Outstanding: 37.1, Excellent: 54.3, "Very Good": 8.6, Good: 0 },
{ category: "2", Outstanding: 52.6, Excellent: 43.3, "Very Good": 3.1, Good: 1.0 },
{ category: "3", Outstanding: 57.0, Excellent: 37.6, "Very Good": 5.4, Good: 0 },
{ category: "4", Outstanding: 43.4, Excellent: 53.3, "Very Good": 2.2, Good: 1.1 },
{ category: "5", Outstanding: 52.4, Excellent: 36.6, "Very Good": 9.8, Good: 1.2 },
{ category: "6", Outstanding: 50, Excellent: 46.3, "Very Good": 3.7, Good: 0 },
];
export const C6viiKey = ["1", "2", "3", "4", "5"];
export const C6vii = [
{ category: "1", 5: 31.1, 4: 34, 3: 23.6, 2: 6.6, 1: 4.7 },
{ category: "2", 5: 33, 4: 27, 3: 26, 2: 8, 1: 6 },
{ category: "3", 5: 21.2, 4: 43.4, 3: 16.2, 2: 14.1, 1: 5.1 },
{ category: "4", 5: 41.2, 4: 33, 3: 18.6, 2: 4.1, 1: 3.1 },
{ category: "5", 5: 54.3, 4: 32.6, 3: 7.6, 2: 3.3, 1: 2.2 },
{ category: "6", 5: 70.3, 4: 18.8, 3: 6.2, 2: 3.1, 1: 1.6 },
];
export const C6viii = {
xValues: ["1", "2", "3", "4", "5", "6"],
lines: [
{ label: "Main rounds", yValues: [60.7, 74.3, 64.6, 64.3, 54.9, 46.4] },
{ label: "Continuous Rounds", yValues: [21.5, 6.9, 6.1, 5.1, 3.3, 0] },
{ label: "Externally", yValues: [17.8, 18.8, 29.3, 30.6, 41.8, 52.3] },
],
};
export const C6ixKey = ["Yes", "No"];
export const C6ix = [
{ category: "1", Yes: 10.5, No: 89.5 },
{ category: "2", Yes: 9.9, No: 90.1 },
{ category: "3", Yes: 6, No: 94 },
{ category: "4", Yes: 10.2, No: 89.8 },
{ category: "5", Yes: 6.4, No: 93.6 },
{ category: "6", Yes: 7.7, No: 92.3 },
];
export const C6xKey = ["Yes", "No"];
export const C6x = [
{ category: "1", Yes: 92.7, No: 7.3 },
{ category: "2", Yes: 98, No: 2 },
{ category: "3", Yes: 98, No: 2 },
{ category: "4", Yes: 95.9, No: 4.1 },
{ category: "5", Yes: 69.1, No: 30.9 },
];

235
data/demographics.ts Normal file
View File

@ -0,0 +1,235 @@
export const D1 = [
{ category: "CS", value: 121 },
{ category: "CS/BBA", value: 7 },
{ category: "CFM", value: 7 },
];
export const D2 = [
{ category: "Man", value: 91 },
{ category: "Woman", value: 42 },
{ category: "Gender non-conforming", value: 3 },
];
export const D3 = [
{ category: "She/Her", value: 42 },
{ category: "He/Him", value: 91 },
{ category: "They/Them", value: 3 },
];
export const D4 = [
{ category: "2001", value: 7 },
{ category: "2000", value: 109 },
{ category: "1999", value: 10 },
{ category: "1998", value: 1 },
];
export const D5 = [
{ category: "Latin", value: 3 },
{ category: "East Asian", value: 92 },
{ category: "Middle Eastern", value: 2 },
{ category: "South Asian", value: 15 },
{ category: "Southeast Asian", value: 8 },
{ category: "White", value: 23 },
{ category: "Other", value: 2 },
];
export const D6 = [
{ category: "No religious affiliation", value: 3 },
{ category: "Christianity", value: 26 },
{ category: "Judaism", value: 3 },
{ category: "Buddhism", value: 3 },
{ category: "Islam", value: 4 },
{ category: "Hinduism", value: 5 },
{ category: "Jainism", value: 1 },
{ category: "Agnosticism", value: 48 },
{ category: "Atheism", value: 42 },
{ category: "Spiritual", value: 2 },
{ category: "Bahá'í Faith", value: 1 },
];
export const D7 = [
{ category: "Asexual", value: 3 },
{ category: "Bisexual", value: 8 },
{ category: "Gay", value: 4 },
{ category: "Heterosexual", value: 117 },
{ category: "Queer", value: 2 },
{ category: "Pansexual", value: 1 },
{ category: "Questioning", value: 4 },
{ category: "Lesbian", value: 1 },
];
export const D8 = [
{ category: "1", value: 28 },
{ category: "1.5", value: 1 },
{ category: "2", value: 88 },
{ category: "3", value: 13 },
{ category: "4", value: 1 },
];
export const D8i = [
{ text: "Mandarin", value: 50 },
{ text: "Chinese", value: 9 },
{ text: "French", value: 19 },
{ text: "Albanian", value: 1 },
{ text: "Cantonese", value: 7 },
{ text: "Russian", value: 4 },
{ text: "Tamil", value: 2 },
{ text: "Hindi", value: 4 },
{ text: "German", value: 1 },
{ text: "Spanish", value: 3 },
{ text: "Ukranian", value: 1 },
{ text: "Vietnamese", value: 1 },
{ text: "Shanghainese", value: 1 },
{ text: "Portugese", value: 1 },
{ text: "Indonesian", value: 1 },
{ text: "Urdu", value: 3 },
{ text: "Gujarati", value: 3 },
{ text: "Korean", value: 3 },
{ text: "Japanese", value: 2 },
{ text: "Romanian", value: 1 },
{ text: "Farsi", value: 1 },
{ text: "Bahasa Indonesian", value: 1 },
{ text: "Marathi", value: 1 },
];
export const D9 = [
{ category: "Moderate Right", value: 15 },
{ category: "Moderate", value: 33 },
{ category: "Left", value: 30 },
{ category: "Moderate Left", value: 41 },
{ category: "Right", value: 3 },
];
export const D10 = [
{ text: "Ontario (Other)", value: 19 },
{ text: "British Columbia", value: 9 },
{ text: "GTA / Toronto", value: 75 },
{ text: "Alberta", value: 5 },
{ text: "Germany", value: 1 },
{ text: "Ecuador", value: 1 },
{ text: "Kitchener / Waterloo", value: 10 },
{ text: "Vietnam", value: 1 },
{ text: "Singapore", value: 2 },
{ text: "Manitoba", value: 1 },
{ text: "Indonesia", value: 1 },
{ text: "UAE", value: 1 },
{ text: "New Brunswick", value: 1 },
{ text: "Quebec", value: 1 },
{ text: "USA", value: 2 },
{ text: "China", value: 3 },
];
export const D11 = [
{ category: "Master's Degree", value: 55 },
{ category: "Doctoral Degree", value: 22 },
{ category: "Bachelor's Degree", value: 44 },
{ category: "High School Diploma", value: 5 },
{ category: "College Diploma", value: 4 },
{ category: "Medical Doctorate", value: 1 },
{ category: "No Diploma", value: 1 },
];
export const D12 = [
{ category: "0k-50k", value: 14 },
{ category: "51k-100k", value: 29 },
{ category: "101k-150k", value: 31 },
{ category: "151k-200k", value: 21 },
{ category: "201k-250k", value: 14 },
{ category: "251k-300k", value: 6 },
{ category: "301k+", value: 11 },
];
export const D13 = [
{ category: "0", value: 91 },
{ category: "1", value: 26 },
{ category: "2", value: 5 },
{ category: "3", value: 3 },
{ category: "4", value: 3 },
{ category: "5", value: 1 },
];
export const D14 = [
{ category: "First", value: 70 },
{ category: "Second", value: 50 },
{ category: "Third and higher", value: 12 },
];
export const D15 = [
{ category: "87", value: 1 },
{ category: "88", value: 0 },
{ category: "89", value: 0 },
{ category: "90", value: 0 },
{ category: "91", value: 2 },
{ category: "92", value: 5 },
{ category: "93", value: 4 },
{ category: "94", value: 7 },
{ category: "95", value: 17 },
{ category: "96", value: 28 },
{ category: "97", value: 24 },
{ category: "98", value: 30 },
{ category: "99", value: 9 },
{ category: "100", value: 1 },
];
export const D16 = [
{ category: "No", value: 43 },
{ category: "Yes", value: 90 },
];
export const D16i = [
{ category: "Waterloo", value: 34 },
{ category: "Toronto", value: 4 },
{ category: "Western", value: 2 },
{ category: "UC Berkeley", value: 2 },
{ category: "Pennsylvania", value: 1 },
{ category: "Michigan", value: 1 },
{ category: "Texas @ Austin", value: 1 },
{ category: "Sheridan", value: 1 },
{ category: "McGill", value: 1 },
{ category: "Princeton", value: 1 },
];
export const D17 = [
{ category: "AP", value: 45 },
{ category: "IB", value: 37 },
{ category: "Gifted", value: 23 },
{ category: "Language Immersion", value: 8 },
{ category: "TOPS", value: 5 },
{ category: "Enriched", value: 5 },
{ category: "Other", value: 5 },
{ category: "CEGEP", value: 1 },
];
export const D18 = [
{ category: "0", value: 2 },
{ category: "2k-3k", value: 34 },
{ category: "3k-4k", value: 6 },
{ category: "4k-5k", value: 10 },
{ category: "5k-6k", value: 9 },
{ category: "6k-7k", value: 2 },
{ category: "7k-8k", value: 5 },
{ category: "8k-9k", value: 5 },
{ category: "9k-10k", value: 0 },
{ category: "10k-20k", value: 21 },
{ category: "20k-30k", value: 2 },
{ category: "30k-40k", value: 2 },
{ category: "40k-50k", value: 2 },
{ category: "93k", value: 1 },
];
export const D19 = [
{ category: "INTP", value: 18 },
{ category: "INTJ", value: 13 },
{ category: "ENTP", value: 11 },
{ category: "ISTJ", value: 10 },
{ category: "INFP", value: 10 },
{ category: "ENFJ", value: 9 },
{ category: "INFJ", value: 8 },
{ category: "ISTP", value: 7 },
{ category: "ENFP", value: 7 },
{ category: "ENTJ", value: 6 },
{ category: "ISFJ", value: 5 },
{ category: "ESTP", value: 4 },
{ category: "ESFJ", value: 3 },
{ category: "ISFP", value: 1 },
];

479
data/friends.ts Normal file
View File

@ -0,0 +1,479 @@
export const F1 = [
{
category: "1",
value: 5,
},
{
category: "2",
value: 4,
},
{
category: "3",
value: 11,
},
{
category: "4",
value: 19,
},
{
category: "5",
value: 17,
},
{
category: "6",
value: 15,
},
{
category: "7",
value: 19,
},
{
category: "8",
value: 6,
},
{
category: "9",
value: 2,
},
{
category: "10",
value: 5,
},
];
export const F2 = [
{
category: "Introvert",
value: 51,
},
{
category: "Extrovert",
value: 11,
},
{
category: "Ambivert",
value: 38,
},
];
export const F3 = [
{
category: "None",
value: 5,
},
{
category: "Half",
value: 25,
},
{
category: "Some",
value: 28,
},
{
category: "Majority",
value: 42,
},
{
category: "All",
value: 3,
},
];
export const F4 = [
{
category: "Rarely",
value: 20,
},
{
category: "Sometimes",
value: 32,
},
{
category: "Often",
value: 33,
},
{
category: "Always",
value: 15,
},
];
export const F5 = [
{
category: "0",
value: 7,
},
{
category: "1-2",
value: 29,
},
{
category: "3-5",
value: 35,
},
{
category: "5-10",
value: 10,
},
{
category: "10+",
value: 6,
},
{
category: "Unsure",
value: 14,
},
];
export const F6 = [
{
category: "Often",
value: 8,
},
{
category: "Sometimes",
value: 37,
},
{
category: "Rarely",
value: 37,
},
{
category: "Never",
value: 17,
},
{
category: "Always",
value: 1,
},
];
export const F7 = [
{
category: "Often",
value: 35,
},
{
category: "Sometimes",
value: 34,
},
{
category: "Rarely",
value: 14,
},
{
category: "Never",
value: 3,
},
{
category: "Always",
value: 14,
},
];
export const F8 = [
{
category: "1A",
value: 52,
},
{
category: "1B",
value: 35,
},
{
category: "2A",
value: 23,
},
{
category: "2B",
value: 26,
},
{
category: "3A",
value: 7,
},
{
category: "3B",
value: 3,
},
{
category: "4A",
value: 7,
},
{
category: "4B",
value: 13,
},
{
category: "1st coop",
value: 7,
},
{
category: "2nd coop",
value: 8,
},
{
category: "3rd coop",
value: 8,
},
{
category: "4th coop",
value: 3,
},
{
category: "5th coop",
value: 5,
},
{
category: "6th coop",
value: 3,
},
];
export const F9 = [
{
category: "0",
value: 1,
},
{
category: "1",
value: 13,
},
{
category: "2",
value: 32,
},
{
category: "3-4",
value: 50,
},
{
category: "5-10",
value: 7,
},
];
export const F10 = [
{
category: "0",
value: 1,
},
{
category: "1-2",
value: 8,
},
{
category: "3-4",
value: 49,
},
{
category: "5-10",
value: 43,
},
{
category: "11+",
value: 1,
},
];
export const F11 = [
{
category: "0",
value: 2,
},
{
category: "1",
value: 9,
},
{
category: "2",
value: 20,
},
{
category: "3",
value: 29,
},
{
category: "4",
value: 27,
},
{
category: "5",
value: 16,
},
];
export const F12 = [
{
category: "All",
value: 4,
},
{
category: "Most",
value: 41,
},
{
category: "Some",
value: 49,
},
{
category: "Barely",
value: 8,
},
{
category: "None",
value: 1,
},
];
export const F13 = [
{
category: "Classes",
value: 81,
},
{
category: "Mutual friends",
value: 71,
},
{
category: "Extracurriculars",
value: 53,
},
{
category: "Coop",
value: 40,
},
{
category: "Parties",
value: 15,
},
{
category: "Online",
value: 9,
},
{
category: "Residence",
value: 3,
},
];
export const F14 = [
{
category: "Res",
value: 78,
},
{
category: "MC",
value: 36,
},
{
category: "DC",
value: 21,
},
{
category: "PAC",
value: 14,
},
{
category: "SLC",
value: 11,
},
{
category: "E7",
value: 9,
},
{
category: "CIF",
value: 5,
},
{
category: "DP",
value: 4,
},
{
category: "E5",
value: 3,
},
{
category: "Plaza",
value: 3,
},
{
category: "AL",
value: 2,
},
];
export const F15 = [
{
text: "Chatting/Talking",
value: 12,
},
{
text: "Eating food",
value: 36,
},
{
text: "Workout",
value: 11,
},
{
text: "Drinking",
value: 7,
},
{
text: "Study",
value: 9,
},
{
text: "Board games",
value: 10,
},
{
text: "Video games",
value: 8,
},
{
text: "Watch TV Shows/Animes/Movies",
value: 4,
},
{
text: "Party",
value: 2,
},
{
text: "Cook",
value: 2,
},
{
text: "Exploring new places",
value: 1,
},
{
text: "Clubs",
value: 1,
},
];
export const F16 = [
{
category: "Most",
value: 48,
},
{
category: "Some",
value: 35,
},
{
category: "All",
value: 9,
},
{
category: "Few",
value: 6,
},
{
category: "None",
value: 2,
},
];

128
data/full-time.ts Normal file
View File

@ -0,0 +1,128 @@
export const F1 = [
{ text: "Adeptmind", value: 1 },
{ text: "Akuna Capital", value: 1 },
{ text: "Amazon", value: 3 },
{ text: "American Express", value: 1 },
{ text: "Anyscale", value: 1 },
{ text: "Apple", value: 1 },
{ text: "Astronomer", value: 1 },
{ text: "Behaviour Interactive Inc.", value: 1 },
{ text: "Bloomberg", value: 2 },
{ text: "Caldera", value: 1 },
{ text: "Capital One", value: 2 },
{ text: "Carbon Neutral Club", value: 1 },
{ text: "Citadel", value: 4 },
{ text: "D.E. Shaw", value: 1 },
{ text: "Databricks", value: 3 },
{ text: "Datadog", value: 2 },
{ text: "Doordash", value: 1 },
{ text: "Enzuzo", value: 1 },
{ text: "Faire", value: 1 },
{ text: "Google", value: 2 },
{ text: "HRT", value: 2 },
{ text: "Huawei", value: 1 },
{ text: "Intuit", value: 1 },
{ text: "Jane Street", value: 5 },
{ text: "LinkedIn", value: 1 },
{ text: "Meta", value: 1 },
{ text: "Microsoft", value: 1 },
{ text: "Nokia", value: 1 },
{ text: "Opal", value: 1 },
{ text: "Relay", value: 1 },
{ text: "RideCo", value: 1 },
{ text: "Riot Games", value: 1 },
{ text: "Rippling", value: 3 },
{ text: "Roblox", value: 1 },
{ text: "Scale AI", value: 1 },
{ text: "SeatGeek", value: 2 },
{ text: "Snowflake", value: 2 },
{ text: "Stripe", value: 2 },
{ text: "Sun Life", value: 1 },
{ text: "Uber", value: 3 },
{ text: "University of Waterloo", value: 1 },
{ text: "Unnamed Financial Trading Firm", value: 1 },
{ text: "Verkada", value: 2 },
{ text: "Waabi", value: 1 },
{ text: "Warp", value: 1 },
{ text: "Whatnot", value: 1 },
{ text: "ZeMind Studios", value: 1 },
];
export const F2 = [
{ text: "New York (NY)", value: 34 },
{ text: "Bellevue (WA)", value: 1 },
{ text: "Seattle (WA)", value: 2 },
{ text: "London (UK)", value: 1 },
{ text: "Calgary (AB)", value: 1 },
{ text: "Vancouver (BC)", value: 2 },
{ text: "Montreal (QC)", value: 1 },
{ text: "Kitchener (ON)", value: 1 },
{ text: "Markham (ON)", value: 1 },
{ text: "Ottawa (ON)", value: 1 },
{ text: "Waterloo (ON)", value: 3 },
{ text: "Toronto (ON)", value: 14 },
{ text: "Chicago (IL)", value: 1 },
{ text: "Cupertino (CA)", value: 1 },
{ text: "Bay Area (CA)", value: 1 },
{ text: "San Jose (CA)", value: 1 },
{ text: "Los Angeles (CA)", value: 1 },
{ text: "San Francisco (CA)", value: 10 },
{ text: "Sunnyvale (CA)", value: 1 },
{ text: "San Mateo (CA)", value: 4 },
];
export const F3 = [
{ category: "1", value: 30 },
{ category: "2", value: 24 },
{ category: "3", value: 13 },
{ category: "4+", value: 10 },
];
export const F4 = [
{ category: "No", value: 22 },
{ category: "Yes", value: 59 },
];
export const F5 = [
{ category: "0-50k", value: 1 },
{ category: "51k-100k", value: 6 },
{ category: "101k-150k", value: 10 },
{ category: "150k-200k", value: 4 },
{ category: "201k-250k", value: 1 },
{ category: "251k+", value: 3 },
];
export const F6 = [
{ category: "150k-200k", value: 3 },
{ category: "201k-250k", value: 7 },
{ category: "251k-300k", value: 17 },
{ category: "301k-350k", value: 12 },
{ category: "351k-550k", value: 6 },
{ category: "551k-700k", value: 9 },
{ category: "701k+", value: 2 },
];
export const F7 = [
{ text: "Finance", value: 12 },
{ text: "Computer Software", value: 60 },
{ text: "Artificial Intelligence", value: 6 },
{ text: "Cloud Computing", value: 11 },
{ text: "Computer Hardware", value: 3 },
{ text: "Operating Systems", value: 3 },
{ text: "Pure Mathematics", value: 1 },
{ text: "Process/Project Management", value: 1 },
{ text: "Data Science and Data Analysis", value: 6 },
{ text: "Web Development", value: 9 },
{ text: "Programming Languages", value: 1 },
{ text: "Research and Development", value: 4 },
{ text: "Robotics", value: 1 },
{ text: "Deep Learning Research", value: 1 },
{ text: "Medical", value: 1 },
{ text: "Game Development", value: 1 },
{ text: "Computer Networking", value: 2 },
{ text: "Product Management", value: 1 },
{ text: "Web Design", value: 3 },
{ text: "Cybersecurity and Ethical Hacking", value: 1 },
{ text: "Security", value: 1 },
{ text: "Product Design/UX Design", value: 1 },
];

243
data/intimacy-and-drugs.ts Normal file
View File

@ -0,0 +1,243 @@
export const I1 = [
{ category: "Alcohol", values: { "Yes, before university": 58, "Yes, during university": 48, No: 12 } },
{ category: "Marijuana", values: { "Yes, before university": 15, "Yes, during university": 49, No: 53 } },
{ category: "Tobacco", values: { "Yes, before university": 6, "Yes, during university": 13, No: 90 } },
{ category: "Magic Mushrooms", values: { "Yes, before university": 2, "Yes, during university": 11, No: 95 } },
{ category: "LSD", values: { "Yes, before university": 0, "Yes, during university": 3, No: 106 } },
{ category: "Cocaine", values: { "Yes, before university": 1, "Yes, during university": 1, No: 107 } },
{ category: "Ecstasy", values: { "Yes, before university": 0, "Yes, during university": 1, No: 108 } },
{ category: "Methamphetamine", values: { "Yes, before university": 0, "Yes, during university": 1, No: 108 } },
{ category: "Other", values: { "Yes, before university": 0, "Yes, during university": 2, No: 91 } },
];
export const I2i = [
{ category: "Yes, before university", value: 36 },
{ category: "Yes, during university", value: 42 },
{ category: "No", value: 41 },
];
export const I2ii = [
{ category: "Before university", value: 35 },
{ category: "1A", value: 6 },
{ category: "1B", value: 7 },
{ category: "2A", value: 7 },
{ category: "2B", value: 3 },
{ category: "3A", value: 2 },
{ category: "3B", value: 6 },
{ category: "4A", value: 9 },
{ category: "4B", value: 2 },
];
export const I3 = [
{ category: "0", value: 30 },
{ category: "1", value: 50 },
{ category: "2", value: 23 },
{ category: "3", value: 9 },
{ category: "4", value: 2 },
{ category: "5", value: 0 },
{ category: "6", value: 0 },
{ category: "7", value: 1 },
];
export const I4 = [
{ category: "0", value: 38 },
{ category: "1", value: 40 },
{ category: "2", value: 10 },
{ category: "3", value: 8 },
{ category: "4", value: 8 },
{ category: "5", value: 2 },
{ category: "6", value: 1 },
{ category: "8", value: 1 },
{ category: "10", value: 1 },
{ category: "18", value: 1 },
{ category: "22", value: 1 },
{ category: "23", value: 1 },
{ category: "29", value: 1 },
{ category: "57", value: 1 },
];
export const I5 = [
{ category: "0-1 year", value: 40 },
{ category: "1-2 years", value: 21 },
{ category: "2-3 years", value: 10 },
{ category: "3-4 years", value: 13 },
{ category: "4+ years", value: 21 },
];
export const I6 = [
{ category: "No", value: 96 },
{ category: "Yes, been cheated on", value: 7 },
{ category: "Yes, cheated on someone", value: 4 },
{ category: "Yes, helped someone cheat", value: 2 },
{ category: "Yes, cheated on and helped", value: 1 },
];
export const I7 = [
{ category: "No", value: 74 },
{ category: "Yes", value: 42 },
];
export const I8 = [
{ category: "No", value: 40 },
{ category: "Yes", value: 26 },
];
export const I9i = [
{ category: "No", value: 58 },
{ category: "Yes", value: 59 },
];
export const I9ii = [
{ category: "Before university", value: 13 },
{ category: "1A", value: 13 },
{ category: "1B", value: 3 },
{ category: "2A", value: 5 },
{ category: "2B", value: 2 },
{ category: "3A", value: 5 },
{ category: "3B", value: 6 },
{ category: "4A", value: 8 },
{ category: "4B", value: 4 },
{ category: "5A", value: 1 },
{ category: "5B+", value: 2 },
];
export const I9iii = [
{ text: "High School", value: 12 },
{ text: "Classes", value: 11 },
{ text: "Mutual Friends", value: 16 },
{ text: "Party", value: 2 },
{ text: "Dating app", value: 4 },
{ text: "Co-op", value: 2 },
{ text: "Orientation", value: 2 },
{ text: "Residence", value: 3 },
{ text: "Extracurriculars", value: 6 },
{ text: "Lab", value: 1 },
{ text: "Aphrodite Project", value: 1 },
{ text: "Childhood Friends", value: 1 },
];
export const I10 = [
{ text: "73", value: 3 },
{ text: "68", value: 2 },
{ text: "64", value: 2 },
{ text: "53", value: 2 },
{ text: "62", value: 2 },
{ text: "54", value: 3 },
{ text: "34", value: 1 },
{ text: "22", value: 3 },
{ text: "46", value: 2 },
{ text: "49", value: 1 },
{ text: "50", value: 5 },
{ text: "58", value: 1 },
{ text: "41", value: 3 },
{ text: "72", value: 1 },
{ text: "56", value: 1 },
{ text: "36", value: 2 },
{ text: "80", value: 2 },
{ text: "66", value: 2 },
{ text: "52", value: 4 },
{ text: "45", value: 1 },
{ text: "60", value: 2 },
{ text: "38", value: 1 },
{ text: "47", value: 3 },
{ text: "81", value: 1 },
{ text: "37", value: 1 },
{ text: "57", value: 2 },
{ text: "69", value: 1 },
{ text: "35", value: 2 },
{ text: "40", value: 3 },
{ text: "70", value: 1 },
{ text: "87", value: 1 },
{ text: "97", value: 1 },
{ text: "75", value: 1 },
{ text: "33", value: 1 },
{ text: "8", value: 1 },
{ text: "95", value: 1 },
{ text: "55", value: 2 },
{ text: "82", value: 1 },
{ text: "32", value: 1 },
{ text: "90", value: 1 },
{ text: "98", value: 2 },
{ text: "88", value: 1 },
{ text: "89", value: 2 },
{ text: "91", value: 2 },
{ text: "30", value: 1 },
{ text: "48", value: 1 },
{ text: "31", value: 1 },
{ text: "25", value: 1 },
{ text: "94", value: 2 },
{ text: "63", value: 1 },
{ text: "93", value: 2 },
{ text: "100", value: 1 },
{ text: "43", value: 1 },
{ text: "42", value: 1 },
];
export const I11 = [
"It's much more important to find someone you can care about than a perfect match.",
"Since I was never in a relationship before university, I didn't really have many expectations for a relationship coming into university. Now, I believe that one of the most important things in a relationship is that you have some activities you enjoy doing together with your partner. Once the initial novelty of the relationship wears off, you still want to be able to have fun together! Additionally, once you get more comfortable with each other it is important to discuss your values and goals for the future, to ensure that you are compatible in that regard.",
"Everyone has different love languages and sometimes you aren't compatible - however, it's always worth the effort to be open minded and to try in love in ways you aren't familiar with.",
"When you're young, it feels like someone you love and loves you back is easy and common, but you realize later on, finding someone like that is very rare.",
"You can have great relationships with people that aren't your partners (ie. friendships). Invest in them because they're what make life fulfilling. Finding a partner will happen naturally when you are confident and comfortable with yourself.",
"rn people are looking for other that give them *that* feeling (excluding relationships after 4+ months) - it really is just a game of giving people that feeling while not having major red flags :P",
"Never forget to invest in yourself first",
"Not everything works out perfectly, you have to put work into maintaining a relationship",
"Had my very first relationship and am finding it much more exciting and less scary than I initially imagined",
"I used to only be able to imagine them as long term commitments but I'm much more open now to different conceptions of relationships and I view them as a connection that is serving you in some way right now, rather than a commitment to a certain kind of future.",
"Yeah, think I got a much better idea of what it takes to make a long-term relationship work. And maintaining a relationship long-distance during COVID-19 was also a learning experience, but overall I'm thankful for the learnings it gave me.",
"People show that they care in different ways",
"It takes much more work to stay in a relationship (and the work is ongoing too) than",
"I realized that compatibility matters so much more than momentary infatuation.",
"It's a lot more work and compromise than I expected",
"It's a lot of luck, it's a lot of time, and it's a risky investment",
"Sometimes there is no right or wrong in relationship but it's more about compatibility. It's the compatibility of values, personalities, hobbies, financial situations, locations, etc. No matter how ideal the relationship seems when it begins, problems like these will still arise.",
"It feels great to have someone I can trust and open up to. Being in a relationship helped me understand myself and others better and become more confident.",
"I've learned what the purpose of relationships are for me, how to communicate with my partners, how to compromise, how to keep mutual emotional and sexual interest.",
"If they're not making you happy anymore, it's time to walk away. Sometimes they can be the right person for you but timing/circumstance (co-op schedule :/) will make it not work out. You have to figure out if you're willing to change plans for each other or let it go.",
];
export const I12 = [
"Try and get to know as many new people as possible, and show a genuine interest in them as a person. The best way to find someone you are compatible with is just forming friendships with people. If you start having feelings for someone, ask them if they would like to go out to dinner/movies/whatever you both enjoy making it clear you want this to be a date.",
"Keep working on yourself, but remember that romantic love is weird and rare and irrational so it's important to remember to just keep pushing forward and shooting shots.",
"Just be yourself and don't be afraid of asking people out",
"At the end of the day it's about happiness. Focus on that.",
"Be yourself, start doing things you are passionate about and enjoy doing, and it will come",
"Partners are meant to help you grow. If you're looking for someone to \"accept you as you are\", you're looking for the wrong thing -- you have to admit there's parts of yourself that could stand to be improved.",
"Just start holding hands with your friends and hope it works out with one of them",
"If you're like maniacally dedicated to finding one, you'll scare people away, but if you don't care at all, you won't take opportunities that arise. Be chill about it, but keep your eyes open.",
"Focus on bettering yourself before getting into one",
"Have a life outside your s/o, keep good friends around.",
"Start by being comfortable with yourself and being alone first.",
"Just get to know more people and eventually you'll find someone who clicks well with you",
'Don\'t worry so much about "checking all the boxes" from the get go it\'s more about "would I rather hang out with this person or be alone" and passing the vibe check at the beginning. People always lie and only show the more beautiful sides of themselves at the beginning so be flexible and open-minded, but also keep yourself safe and be skeptical.',
"Don't talk to someone for the sake of trying to get in a relationship. Talk to them for the sake of getting to know them and seeing if they are someone you can get along with.",
"You'll never get into one unless you are ACTIVELY trying to and spending time on it.",
"1. seek introspection\n2. seek self-improvement\n3. ???\n4. acquire soul mate\n5. ggez",
"Don't try too hard. It wouldn't work if there's no chemistry.",
"Go meet new people! Talk to people in your class, attend clubs, meet friends of your friends, keep in touch with your co-op friends!",
"1. Don't rush. Aim to become close friends first. 2. Be authentic. 3. Emotional maturity is underrated.",
'Ask yourself "Why would someone want to date me? What can I offer?"',
];
export const I13 = [
"Don't take your partner for granted! Even when you're busy, make sure to check in with your partner and ensure that they do not feel neglected. Also, if your partner does something that bothers you, take some time to calm down and then talk to them about it! The only way you can have less disagreements in the future is if you discuss why you dislike certain things.",
"Make time to connect and strengthen your relationship",
"Communication is the most important thing. Relationships take work from both people, but the sum of the effort greatly exceeds what is put in",
"Communication is really important, don't be afraid to have the serious talks.",
"Partners are meant to help you grow. If you're looking for someone to \"accept you as you are\", you're looking for the wrong thing -- you have to admit there's parts of yourself that could stand to be improved.",
"Be true to yourself",
"You have to really appreciate your partner because it's really easy to take them for granted.",
"Be willing to admit when you're wrong or have made a mistake",
"Communication and openness is everything.",
"Keep it up!",
"What I've learned is that a partnership is necessarily 50/50. Compromising really is a thing you have to do to make a relationship work, but I think what's more important is having a partner who recognizes when you make compromises, is willing to make them for you, and is honest with you about their needs and feelings. What I've learned is that while there are a million things that could break a relationship, as long as you and your partner wake up everyday feeling like there is no challenge you aren't willing to overcome together because that's how much your relationship means to you, then there's nothing to fear.",
"Communication is important, even about the little things",
"Be open and understanding. Your partner doesn't have to think like you.",
"spend as much time as you can together, physically",
"PDA isn't always cute",
"Know what you are getting yourself into and clarify what each party wants",
"Even when you fight, you're on the same side.",
"Communicate about small problems so they don't turn into big problems",
"Never stay in a relationship that is hurting you or holding you back. A relationship should always add to your life.",
"It's ok to be a \"bad partner\" and be with a \"bad partner\" as long as discontentment is communicated in a healthy manner and both people are committed to growing. No one is born and angel (including ourselves) and it's completely normal to have disagreements and have things that anger you or your partner. It's not about how often you fight, it's about how you fight and what happens after the fight.",
];

View File

@ -0,0 +1,426 @@
export const L1 = [
{ category: "Never religious", value: 88 },
{ category: "No longer religious", value: 10 },
{ category: "Became religious", value: 3 },
{ category: "Changed Religions", value: 2 },
{ category: "Still religious", value: 25 },
];
export const L2 = [
{ category: "Yes", value: 83 },
{ category: "No", value: 10 },
{ category: "Knew", value: 40 },
];
export const L3 = [
{ category: "Weekly", value: 93 },
{ category: "Once every few weeks", value: 16 },
{ category: "Monthly", value: 11 },
{ category: "Once every few months", value: 9 },
{ category: "Never", value: 3 },
];
export const L4 = [
{ category: "1", value: 25 },
{ category: "2", value: 24 },
{ category: "3", value: 37 },
{ category: "4", value: 17 },
{ category: "5", value: 17 },
{ category: "6", value: 8 },
{ category: "7", value: 4 },
];
export const L5 = [
{ category: "Strongly agree", value: 24 },
{ category: "Agree", value: 52 },
{ category: "Neutral", value: 21 },
{ category: "Disagree", value: 27 },
{ category: "Strongly disagree", value: 8 },
];
export const L6 = [
{ category: "Few times a week", value: 1 },
{ category: "Weekly", value: 6 },
{ category: "Once every few weeks", value: 19 },
{ category: "Monthly", value: 15 },
{ category: "Once every few months", value: 50 },
{ category: "Never", value: 42 },
];
export const L7 = [
{ category: "9PM-11PM", value: 6 },
{ category: "11PM-1AM", value: 53 },
{ category: "1AM-3AM", value: 58 },
{ category: "3AM-5AM", value: 16 },
];
export const L8 = [
{ category: "0-2", value: 1 },
{ category: "3-4", value: 2 },
{ category: "5-6", value: 25 },
{ category: "7-8", value: 88 },
{ category: "9+", value: 14 },
];
export const L9 = [
{ category: "Few times a week", value: 1 },
{ category: "Weekly", value: 1 },
{ category: "Once every few weeks", value: 18 },
{ category: "Monthly", value: 7 },
{ category: "Once every few months", value: 51 },
{ category: "Never", value: 56 },
];
export const L10 = [
{ category: "0", value: 6 },
{ category: "1", value: 21 },
{ category: "2", value: 34 },
{ category: "3", value: 29 },
{ category: "4", value: 16 },
{ category: "5", value: 11 },
{ category: "6", value: 9 },
{ category: "7", value: 7 },
];
export const L11 = [
{ text: "Gol's", value: 14 },
{ text: "Lazeez Shawarma", value: 3 },
{ text: "Better Chef", value: 2 },
{ text: "Yunshang Rice Noodle", value: 8 },
{ text: "Tims", value: 1 },
{ text: "Ken's Sushi", value: 4 },
{ text: "Kismet", value: 1 },
{ text: "Subway", value: 2 },
{ text: "Kinkaku", value: 1 },
{ text: "Mel's", value: 2 },
{ text: "Foodie Fruitie", value: 3 },
{ text: "Fresh Burrito", value: 2 },
{ text: "Mr Paninos", value: 1 },
{ text: "Taiwanese Garden", value: 1 },
{ text: "Lil Pot", value: 1 },
{ text: "Waterloo Star", value: 3 },
{ text: "Kim's Kitchen", value: 2 },
{ text: "Fantastic Wok", value: 1 },
{ text: "Nuri Village", value: 2 },
{ text: "FRSH", value: 1 },
{ text: "Jinzakaya", value: 1 },
{ text: "Harveys", value: 1 },
{ text: "Shawerma Plus", value: 5 },
{ text: "Rolltations", value: 1 },
{ text: "Osmow's", value: 1 },
{ text: "Math CnD", value: 4 },
{ text: "Poke Box", value: 2 },
{ text: "Omni Palace", value: 1 },
{ text: "Shinwa", value: 4 },
{ text: "Owl of Minerva", value: 1 },
{ text: "Baba Chicken", value: 2 },
{ text: "Bao", value: 2 },
{ text: "Onnuri", value: 2 },
{ text: "Kelsey's", value: 1 },
{ text: "Church's Chicken", value: 1 },
{ text: "The China Bowl", value: 1 },
{ text: "Princess Cafe", value: 1 },
{ text: "Molly's Pub", value: 1 },
{ text: "Top Chicken", value: 1 },
{ text: "Yin's", value: 1 },
{ text: "Bubble tea", value: 1 },
{ text: "iPho", value: 2 },
{ text: "Yummy Chongqing", value: 1 },
{ text: "The Works", value: 1 },
{ text: "LooBapBap", value: 1 },
{ text: "Ennio's", value: 1 },
{ text: "Graduate House", value: 1 },
{ text: "None", value: 1 },
{ text: "Pita Factory", value: 1 },
{ text: "Song's Noodles", value: 1 },
{ text: "Burger King", value: 2 },
];
export const L12 = [
{ text: "Board Games", value: 4 },
{ text: "Orientation", value: 4 },
{ text: "WISA", value: 1 },
{ text: "mathNEWS", value: 5 },
{ text: "Poker", value: 2 },
{ text: "Volleyball", value: 10 },
{ text: "Breakers", value: 1 },
{ text: "Human VS Zombies", value: 2 },
{ text: "None", value: 1 },
{ text: "Math Ambassadors", value: 1 },
{ text: "Dodgeball", value: 3 },
{ text: "Imprint", value: 2 },
{ text: "Midnight Sun Design Team", value: 1 },
{ text: "CCF", value: 2 },
{ text: "Game Dev", value: 1 },
{ text: "CTRL A", value: 1 },
{ text: "iGEM", value: 1 },
{ text: "Dance", value: 1 },
{ text: "Culture Clash Theatre", value: 1 },
{ text: "Quidditch", value: 1 },
{ text: "Softball", value: 1 },
{ text: "MSA", value: 1 },
{ text: "Frisbee", value: 12 },
{ text: "CSC", value: 5 },
{ text: "DDR", value: 1 },
{ text: "DDC", value: 1 },
{ text: "Hockey", value: 2 },
{ text: "Design teams", value: 2 },
{ text: "Squash", value: 1 },
{ text: "Cheese Club", value: 1 },
{ text: "Ballroom Dance", value: 2 },
{ text: "Toastmaster", value: 1 },
{ text: "ICSN", value: 1 },
{ text: "Limelight", value: 1 },
{ text: "Korean Culture", value: 1 },
{ text: "Waterloop", value: 1 },
{ text: "FEDS Volunteering Center", value: 1 },
{ text: "WAT is Zine", value: 1 },
{ text: "Basketball", value: 9 },
{ text: "Orchestra", value: 3 },
{ text: "Student Council", value: 1 },
{ text: "Futsal", value: 1 },
{ text: "Fencing", value: 1 },
{ text: "Fintech", value: 1 },
{ text: "Blockchain", value: 1 },
{ text: "ICE", value: 2 },
{ text: "WATonomous", value: 3 },
{ text: "UWCSA", value: 1 },
{ text: "Intramurals", value: 2 },
{ text: "Table Tennis", value: 1 },
{ text: "Quizbowl", value: 1 },
{ text: "WiCS", value: 4 },
{ text: "Blueprint", value: 2 },
{ text: "Badminton", value: 8 },
{ text: "Band", value: 1 },
{ text: "Cafts 4 Charity", value: 1 },
{ text: "CoffeeNCode", value: 1 },
{ text: "HipHop", value: 3 },
{ text: "Muay Thai", value: 2 },
{ text: "WatLock", value: 1 },
{ text: "Soccer", value: 9 },
{ text: "Animusic", value: 1 },
{ text: "Taekwondo", value: 1 },
{ text: "Hack The North", value: 1 },
{ text: "StarterHacks", value: 1 },
{ text: "Chamber Choir", value: 1 },
{ text: "Latin Dance", value: 1 },
{ text: "DSC", value: 4 },
{ text: "Osu", value: 1 },
{ text: "Visual Arts", value: 1 },
{ text: "Phys", value: 1 },
{ text: "Smash", value: 2 },
{ text: "AcaBellas", value: 1 },
{ text: "Cheerleading", value: 1 },
{ text: "Jam Network", value: 1 },
{ text: "A Cappella", value: 3 },
{ text: "Cuban Salsa", value: 1 },
{ text: "Chabad", value: 1 },
{ text: "Concrete Design Team", value: 1 },
{ text: "MATH Residence Tutor", value: 1 },
{ text: "uWaft", value: 1 },
{ text: "UWACC", value: 2 },
{ text: "Tech+", value: 3 },
{ text: "MathSoc", value: 7 },
{ text: "PMAMCO", value: 8 },
{ text: "Spikeball", value: 1 },
{ text: "PMC", value: 1 },
{ text: "Lacrosse", value: 1 },
{ text: "Recreational Sports", value: 1 },
{ text: "UWICA", value: 1 },
{ text: "SERVE", value: 6 },
{ text: "TCF", value: 1 },
{ text: "MLSB", value: 1 },
{ text: "Rocket League", value: 1 },
{ text: "MEF Board", value: 1 },
];
export const L13 = [
{ category: "DC", value: 26 },
{ category: "MC", value: 22 },
{ category: "E5/E7", value: 15 },
{ category: "DP", value: 10 },
{ category: "SLC", value: 9 },
{ category: "EV", value: 8 },
{ category: "Res", value: 6 },
{ category: "QNC", value: 6 },
{ category: "PHY", value: 2 },
{ category: "CGR", value: 2 },
{ category: "STC", value: 2 },
{ category: "Other", value: 6 },
];
export const L14 = [
{ text: "Rocket League", value: 1 },
{ text: "Gaming", value: 21 },
{ text: "Board games", value: 8 },
{ text: "Poker", value: 1 },
{ text: "Writing", value: 6 },
{ text: "Piano", value: 7 },
{ text: "Badminton", value: 14 },
{ text: "Programming/Coding", value: 5 },
{ text: "DanceDanceRevolution", value: 1 },
{ text: "Drawing", value: 8 },
{ text: "Digital art", value: 2 },
{ text: "Music", value: 11 },
{ text: "Gym", value: 9 },
{ text: "Violin", value: 3 },
{ text: "Sleep", value: 1 },
{ text: "Skating", value: 2 },
{ text: "TV", value: 4 },
{ text: "Video games", value: 19 },
{ text: "Reading", value: 19 },
{ text: "Soccer", value: 7 },
{ text: "Math", value: 2 },
{ text: "Knitting", value: 1 },
{ text: "Climbing", value: 8 },
{ text: "Volleyball", value: 6 },
{ text: "Eating", value: 1 },
{ text: "Watching Basketball", value: 1 },
{ text: "Watching UFC", value: 1 },
{ text: "Going Out", value: 1 },
{ text: "Ultimate Frisbee", value: 4 },
{ text: "Snowboarding", value: 2 },
{ text: "Astronomy", value: 1 },
{ text: "Guitar", value: 6 },
{ text: "F1", value: 2 },
{ text: "Watching Tennis", value: 1 },
{ text: "Crochet", value: 1 },
{ text: "Running", value: 6 },
{ text: "Art", value: 2 },
{ text: "Cooking", value: 11 },
{ text: "Swimming", value: 4 },
{ text: "Skiing", value: 2 },
{ text: "Dancing", value: 9 },
{ text: "Painting", value: 2 },
{ text: "Skateboarding", value: 1 },
{ text: "Powerlifting", value: 1 },
{ text: "Karaoke", value: 1 },
{ text: "DnD", value: 5 },
{ text: "YuGiOh", value: 1 },
{ text: "Getting Drunk", value: 1 },
{ text: "Kpop", value: 3 },
{ text: "Fashion", value: 1 },
{ text: "Accordion", value: 1 },
{ text: "Movie", value: 2 },
{ text: "Shopping", value: 1 },
{ text: "Traveling", value: 3 },
{ text: "Basketball", value: 9 },
{ text: "League", value: 1 },
{ text: "Pokemon", value: 1 },
{ text: "Baking", value: 1 },
{ text: "Singing", value: 6 },
{ text: "Biking", value: 1 },
{ text: "Hockey", value: 2 },
{ text: "Racing", value: 1 },
{ text: "Film", value: 1 },
{ text: "Boxing", value: 1 },
{ text: "Weightlifting", value: 3 },
{ text: "Outdoors", value: 1 },
{ text: "Bassoon", value: 1 },
{ text: "Music Production", value: 2 },
{ text: "Felting", value: 1 },
{ text: "Anime", value: 4 },
{ text: "Bodybuilding", value: 1 },
{ text: "Walking", value: 4 },
{ text: "Quidditch", value: 1 },
{ text: "Crafting", value: 1 },
{ text: "Design", value: 2 },
{ text: "Chess", value: 1 },
{ text: "Politics", value: 2 },
{ text: "Debate", value: 1 },
{ text: "Jogging", value: 1 },
{ text: "Calligraphy", value: 1 },
{ text: "Stardew Valley", value: 1 },
{ text: "Sports", value: 1 },
{ text: "Bass", value: 2 },
{ text: "Kickboxing", value: 1 },
{ text: "Photography", value: 2 },
{ text: "Animating", value: 1 },
{ text: "Horseback Riding", value: 1 },
{ text: "Table Tennis", value: 2 },
{ text: "Origami", value: 1 },
{ text: "Teamfight Tactics", value: 1 },
{ text: "Manga", value: 1 },
{ text: "Rearranging Furniture", value: 1 },
{ text: "Flying planes", value: 1 },
{ text: "Curling", value: 1 },
{ text: "None", value: 1 },
{ text: "Camping", value: 1 },
{ text: "Physics", value: 1 },
{ text: "Psychology", value: 1 },
{ text: "Pooling", value: 1 },
{ text: "Adrenaline Activities", value: 1 },
];
export const L15 = [
{ category: "0", value: 16 },
{ category: "1", value: 53 },
{ category: "2", value: 22 },
{ category: "3-4", value: 15 },
{ category: "5-6", value: 10 },
{ category: "7-8", value: 2 },
{ category: "9+", value: 6 },
];
export const L16 = [
{ category: "The Alley", value: 24 },
{ category: "Gong Cha", value: 10 },
{ category: "Coco", value: 23 },
{ category: "Now Tea", value: 16 },
{ category: "Xing Fu Tang", value: 4 },
{ category: "Chatime", value: 8 },
{ category: "Sweet Dreams", value: 9 },
{ category: "Onezo Tapioca", value: 1 },
{ category: "Machi Machi", value: 6 },
{ category: "O-Hime", value: 1 },
{ category: "Lait Night", value: 2 },
{ category: "Tea Talk", value: 1 },
];
export const L17 = [
{ category: "Shawarma Plus", value: 38 },
{ category: "Lazeez", value: 32 },
{ category: "iPotato", value: 19 },
{ category: "Osmow's", value: 5 },
{ category: "Mozy's", value: 6 },
{ category: "Sultans", value: 1 },
];
export const L18 = [
{ category: "Daily", value: 21 },
{ category: "Few times a week", value: 34 },
{ category: "Weekly", value: 19 },
{ category: "Once every few weeks", value: 17 },
{ category: "Monthly", value: 4 },
{ category: "Once every few months", value: 25 },
{ category: "Never", value: 8 },
];
export const L19 = [
{ category: "All", value: 6 },
{ category: "Most", value: 57 },
{ category: "Half", value: 26 },
{ category: "Some", value: 37 },
{ category: "None", value: 3 },
];
export const L20 = [
{ category: "Always", value: 26 },
{ category: "Often", value: 37 },
{ category: "Sometimes", value: 32 },
{ category: "Rarely", value: 24 },
{ category: "Never", value: 9 },
];
export const L21 = [
{ text: "O-Week", value: 2 },
{ text: "Extracurriculars", value: 20 },
{ text: "Classes", value: 26 },
{ text: "High school", value: 37 },
{ text: "Mutual friends", value: 26 },
{ text: "Residence", value: 8 },
{ text: "Co-op", value: 7 },
{ text: "CSC", value: 1 },
{ text: "Parties", value: 1 },
{ text: "Everywhere", value: 1 },
];

147
data/mental-health.ts Normal file
View File

@ -0,0 +1,147 @@
export const H1 = [
{ category: "Yes", value: 91 },
{ category: "No", value: 34 },
];
export const H2 = [
{ category: "Yes", value: 100 },
{ category: "No", value: 25 },
];
export const H3 = [
{ category: "Yes", value: 31 },
{ category: "No", value: 53 },
{ category: "No, but considered", value: 41 },
];
export const H4 = [
{ category: "Yes", value: 27 },
{ category: "No", value: 66 },
{ category: "No, but considered", value: 32 },
];
export const H5 = [
{ category: "Yes", value: 19 },
{ category: "No", value: 104 },
];
export const H5i = [
{ category: "1", value: 4 },
{ category: "2", value: 7 },
{ category: "3", value: 8 },
{ category: "4", value: 1 },
{ category: "5", value: 2 },
];
export const H6 = [
{ category: "1", value: 6 },
{ category: "2", value: 18 },
{ category: "3", value: 33 },
{ category: "4", value: 42 },
{ category: "5", value: 10 },
];
export const H7 = [
"you have to be happy with what you have and excited for the future. ie you, the world, your future all need to work together to not be depressed. It hit me because i never had a relationship and i feel unlovable - which I assume is a common feeling. So to stay happy you have to be happy for the things you do have, which, if you're here you definitely do",
"University can be a tough time, especially for such a tough program like UW CS. If you feel challenged, remember that it is normal and if you breezing through everything you aren't really learning anything. I know it's easier said than done, but comparison is the thief of joy.",
"Look for hobbies that you truly enjoy that have absolutely nothing at all to do with your major, and make friends through your hobbies.",
"waterloo needs better and actual QUALITY mental health resources",
"Good friends often lead to good mental health",
"One thing I struggled with with respect to my mental health is living by myself and establishing healthy patterns for myself. I noticed during covid that while I was living at home, it was easy for me to fall into the patterns my family has established. This helped my mental health while I was at home. However, when living by myself I had to re-discover for myself the importance of many of these habits and patterns before I was able to successfully manage my mental health. This is still a work in progress, but I am optimistic!",
"Always put mental health in the first place!!!",
"Reach out for help from the professors/instructional assistants. They are actually surprisingly accommodating and supportive. I wish I wasn't afraid to ask for extensions when I needed it earlier - the staff/lecturers actually really care.",
"Never compare yourself with others, don't get stressed from other people's achievements, focus on yourself.",
"When moving across the country, it's normal to feel lonely or homesick! Don't be afraid to call home or get counselling/therapy. Having/making friends in a similar situation can also help.",
"Talk to your friends about it. They might be going through the same thing and may need someone to talk to as well.",
"Seek help even if just considering it.",
"Tbh I think it was just realizing how messed up the world is. I certainly felt disillusioned after co-op showed me what the job market is really like and just realizing that things I did that I considered unethical actually got me ahead in life.",
"Personally, everything I strive for is in order to live happily. Keeping this in mind helps me prioritize my mental health.",
"Some people and profs are more understanding than others. Sometimes it's difficult to discuss mental health, even if doing so might be beneficial.",
"you have to actually work on it. I don't think it's that bad, just sleep well eat well exercise and for most people it falls into place. Watch your mentalities. I guess that's hard, but doable.",
"Please put your health as a priority and continue to reach out for help even if it feels like people are saying no to you. Make sure to reach out early and document your visits incase you ever need it for a petition.",
"It was better than high school because resources like Health Services felt more accessible once i had autonomy",
"Socialization helped to deal with the stress from study",
"Organize your day based on what activity drains your energy the most, and sleep",
];
export const H8 = [
"Exercise, sleep, talk to friends + family, relax. When applicable, accept that losing X% on an assignment isn't going to impact my final mark or my life course in any meaningful way",
"I enjoy reading books on philosophy and psychology, as well as spending time reflecting on my priorities and outlook on life. While this helps me, I still get stuck in extremes sometimes and I tend to look for perspectives that support how I am feeling at the time. Hence, one of the most important things for me was talking to my partner when I was struggling. A critical perspective on my individual situation was the most effective at changing my view of my problems.",
"Indulged myself in my artistic endeavours, immersed myself in meaningful / challenging work, lift weights + sleep + eat well, and get support from friends / family.",
"Listen to music, walking alone",
"Do something that makes me happy and put annoying stuff aside for a bit",
"Hanging out with friends, exercising, playing games",
"Get outside more. Exercise more. Hang out with friends.",
"Hang out with friends/girlfriend",
"Go out for a walk.",
"Talked with friends/family, got counselling",
"Relax by reading, or to organize by concerns in a calendar or spreadsheet",
"Journal and exercise",
"Talking to someone (friends, family, therapist)",
"Sports, playing games with friends",
"Focus on good habits",
"Listening to cartoon women whisper empty words into my ears.",
"Eat spicy food, do sports, and cry.",
"Vitamin D is really important to keep yourself happy! Make sure to take Vitamin D supplements especially in the winter and go out for walks! I loved taking walks on sunny mornings in winter while listening to light music, it really improved my mental health!",
"Take a day off and treat myself to good food. Talking with friends.",
"Talk with friends, do chores/exercise (easy productive tasks), reduce school workload.",
];
export const H9 = [
'I would enjoy more materials available on how to balance work and leisure, and general philosophy on how to find meaning in life. While UW does have some online materials on this, they tend to be very generic ("make sure to take breaks"). I would prefer some events during orientation where graduate students/professors discuss their personal journey to find meaning in life and balancing different aspects of life.',
"I think the co-op system needs to be reworked so it's not just exploiting cheap labour. I also feel like a lot of the systems in place don't make you feel like a person, just a number. Administration ALWAYS gave me trouble with course selection but all of the problems would just be resolved in a day if I spoke with the professors directly. There are people who care, but the system is built so that YOU have to find them, and for people already struggling, this is a huge barrier to them getting help.",
"Provide more support and accommodations for students. Another important aspect is making those accommodations more easily accessible. It's hard to worry about that ontop to mental health issues.",
"Make mental health resources more accessible (have some guarantee to get a counsellor, make it easier to book an appointment, reduce wait times, etc).",
"Better counselling services",
"Send a message that even mild mental health problems like burnout and isolation deserve attention.",
"Hire profs that care about mental health issues",
"Good study environment, more student involvement, find good and professional instructors",
"Nothing, really. I think that UW inherently puts people under stress, but those stressful things are what most people come for. I can't comment on their services because I haven't used them. Don't rank engineering students though? That's toxic as hell.",
"Stop using the final 50%~100% marking scheme",
"provide quality services",
"Get more counselors and psychiatrists. People need actual medication.",
"Foster a better campus environment. We don't have a lot of comfortable lounging/kickback places on campus (especially in the winter) where people can go to bump into people, relax, and just kill an hour or two. As a result, we're all hanging out in our apartments or elsewhere which is usually smaller groups having some people left out. Just having those kinda spaces on campus would make a work of difference.",
"Expand the PAC gym so I don't have to wait 30 minutes for a deadlift platform.",
"Provide better communication, resources",
"more public pianos",
"Provide more free food to students to encourage them to go out and take a break.",
"Late days really help.",
"Therapy services",
"I think the school does ok honestly.",
];
export const H10 = [
{ category: "1", value: 19 },
{ category: "2", value: 15 },
{ category: "3", value: 30 },
{ category: "4", value: 35 },
{ category: "5", value: 18 },
];
export const H11 = [
"Everything that I have achieved or been successful at has been the result of meticulous and many many years of sweat and blood. Why would I have imposter syndrome for things that I worked so hard to achieve? I earned it.",
"Occured after last coop when I didn't get a return offer for Full-Time employment. I feel like I'm not cut out for software dev. Haven't gotten over it yet",
"Occurred when I received high GPA, and I felt like I did not deserve it. However, the imposter syndrome usually went away in a couple days.",
'Many of my friends are (or appear) much higher achieving than me; I tend to get the lowest grades out of my group and I ended up at the "worst" company out of all of the friends in my group. However, I recognize that I am in a very small bubble and that in the grand scheme of things (at UW, at Waterloo, in Canada, or beyond) I am doing very well and I shouldn\'t compare myself to other people so much.',
"I sometimes doubt myself, but what helped me cope were the WICS panels where the successful panelists talked about their own experience with imposter syndrome.",
"I overcame it because I remembered I don't want a coding related job anyways lol",
"I transferred into CS in 2nd year with absolutely no coding experience. Most of my friends had been coding since high school, and everyone I met was super passionate about software. I think I overcame it by simply putting in the work (because I enjoyed the subject) and gaining more knowledge. Coop terms also helped a lot - I definitely grew the most as a software engineer at work.",
"The culture can sometimes be toxic. It's hard to get to know someone for the sake of knowing them; people are too focused on co-op and leetcode grinding.",
"I'm him. I've never felt like an imposter. I've felt bad at my job, and kind of dumb in some courses, but I'm a student or a coop. I'm there to learn, I can learn anything, and I can get better at anything. I earned my spot, I worked hard to get to where I am, I'm not an imposter.",
"I have achievements on paper but I don't feel like I deserve them or that they're meaningful.",
"I was academically strong in highschool but had no coding experience going into University.",
"I realized most other people are going through the same thing",
"I don't know a lot of things, but the more I observe the world around me, nobody around me really does either... except they are much more successful than me, so I'm clearly missing something.",
"I knew back in high school that I was never the best in school, In university, I realized there are even smarter students who are more capable. However, I don't think I was ever intimidated because I always focused on myself. I pursued my interest, explored where I want to be, and as university went on I had a clearer vision of it. For example, I realized half way through uni that I am more interested in product design rather than coding, so I built a portfolio and a personal website, switched my job search routines, then started working in UX/UI design. Some people would tell me “designers don't earn as much”, or “it's a waste of your CS degree, look at how others in your program are already getting dev offers from big tech firms”, etc. I am really glad I didn't get intimidated by these negative comments because I love my new job as a designer. The knowledge from my CS degree still comes in handy at work!",
"Throughout university, you will hear a lot about people getting offers from big Cali companies or the phrase “Cali or Bust” (which is not true, you can find good jobs anywhere!) Instead of listening to others, it's more helpful to just focus on yourself. I don't really feel imposter syndrome because I try to enjoy the most of my life including my job, and I am satisfied with where I am. I also think that everyone lives and grows at their own pace, sometimes we are so focused on others' achievements and tend to ignore our own growth. Last but not least, it's essential to keep a positive attitude. I try to see others' achievements more as ways to motivate myself. I believed in my own capabilities or at least I believe that if I keep trying, I will reach my goals eventually. And that really helped me throughout university.",
"One of my big insecurities is that I only get jobs because I'm a woman in CS and I'm not actually good enough and just there as a diversity hire",
"Think I was just placing too much of my self-worth into my grades, especially cause grades are such an easy concrete way you can compare yourself to your peers and feel less than. Truthfully, I think one of the big things I did was I just started being up front with myself and my friends about my weaknesses. It was when my grades were always a secret and a source of shame that I felt so horrible and my self esteem went down the drain. After I just started telling people the truth (parents and friends included) and just telling myself that it was okay that I wasn't the best student anymore as long as I was giving it my best, I just felt this huge burden being lifted off me. And in a weird way, once I accepted that it was okay that I wasn't the best when it came to studying for calculus tests or if certain topics didn't come easy to me, I was able to put that energy into actually learning and that's why I really saw my marks improve in my later uni years. Additionally, I just learned how to be patient with myself when learning and got better at setting study goals, organizing my time, and figuring out what studying techniques worked for me. So overall, I think what I learned over university is self-acceptance, patience, and learning how to feel confident even while being honest with myself and others about my shortcomings.",
"I've deliberately put myself in uncomfortable positions to grow, so I've experienced it in places like leadership roles. You overcome these things with practice and experience.",
"Trust yourself and focus on yourself; do not compete with others and do your best",
"It was very prevalent all the way until around halfway through my final co-op when I felt like I actually belonged where I was.",
"In first year, there were people who got really good co-ops (at the time). The people who worked at Wish, Google, Microsoft, or other US companies were all kind of mini celebrities in the CS circles. I think there's really no way to cope. Part of it is improving and working on yourself and part of it is accepting that there will always be people who are better.",
"Sometimes, it feels like I'm not good enough for something after seeing many students in the same year as me get good co-op and internships.",
"I realized most people feel similarly, but it's not outwardly visible. Everyone shows their best side in a professional setting. Also I'm at the beginning of my career. I have a lot of time to learn.",
"When I first got to university, I immediately realized that I'm now surrounded by individuals just as if not more capable, driven, and talented as I am. And I came to the conclusion that clinging on to the same high-school mindset of being \"the best\" is counterproductive and detrimental to mental health. Not sure if I can say I overcame it, but some ways that helped me through was to first ditch my ego and second understand that being surrounded by people smarter than me means I'm leading and improving myself, it means that I have much more to gain. However, eventually you will realize most if not all other people have the exact same feeling, they might feel that they aren't as capable as YOU are. So it is really helpful to talk to your friends and peers to gain an understanding of their perspective :).",
"Seeing numerous LinkedIn posts about people who bragged about their coop really made it worse. I overcame by talking to more people about it.",
];

380
data/miscellaneous.ts Normal file
View File

@ -0,0 +1,380 @@
export const M1 = [
{
category: "Almost every day",
value: 8,
},
{
category: "A few times weekly",
value: 8,
},
{
category: "A few times monthly",
value: 25,
},
{
category: "Rarely",
value: 69,
},
];
export const M2 = [
{
category: "0",
value: 12,
},
{
category: "1",
value: 32,
},
{
category: "2",
value: 23,
},
{
category: "3",
value: 13,
},
{
category: "4",
value: 4,
},
{
category: "5",
value: 2,
},
{
category: "6",
value: 3,
},
{
category: "7",
value: 3,
},
{
category: "8",
value: 3,
},
{
category: "9",
value: 1,
},
{
category: "10",
value: 4,
},
];
export const M3 = [
{
category: "CS / CS/BBA / CFM",
value: 84,
},
{
category: "Software Engineering",
value: 6,
},
{
category: "Psychology",
value: 2,
},
{
category: "FARM",
value: 1,
},
{
category: "BBA",
value: 1,
},
];
export const M4 = [
{
category: "Yes",
value: 27,
},
{
category: "No",
value: 73,
},
];
export const M5 = [
{
category: "Yes",
value: 16,
},
{
category: "No",
value: 84,
},
];
export const M6 = [
{
text: "Go to UofT",
value: 33,
},
{
text: "UBC",
value: 9,
},
{
text: "A different university...",
value: 15,
},
{
text: "UOttawa",
value: 1,
},
{
text: "Start a business",
value: 5,
},
{
text: "Take a gap year and try again",
value: 8,
},
{
text: "Learn a trade",
value: 3,
},
{
text: "UofWindsor",
value: 3,
},
{
text: "Start working",
value: 1,
},
{
text: "Travel",
value: 2,
},
{
text: "UAlberta",
value: 1,
},
{
text: "McGill",
value: 1,
},
{
text: "Stanford",
value: 1,
},
{
text: "UIUC",
value: 1,
},
{
text: "No idea",
value: 3,
},
{
text: "Die...",
value: 3,
},
{
text: "Teacher's College",
value: 2,
},
{
text: "Resting and Learning",
value: 1,
},
{
text: "Be a doctor",
value: 2,
},
{
text: "Study biology",
value: 2,
},
];
export const M7 = [
{
text: "Communication",
value: 4,
},
{
text: "Become more social",
value: 7,
},
{
text: "Cooking",
value: 12,
},
{
text: "Handling stress",
value: 3,
},
{
text: "Dance",
value: 4,
},
{
text: "Sing",
value: 3,
},
{
text: "Weightlifting",
value: 2,
},
{
text: "Snowboard",
value: 2,
},
{
text: "Improved Relationship",
value: 5,
},
{
text: "Public Speaking",
value: 2,
},
{
text: "Self-confidence",
value: 6,
},
{
text: "Video games",
value: 5,
},
{
text: "Grown as a Person",
value: 2,
},
{
text: "Rock climbing",
value: 3,
},
{
text: "Guitar",
value: 2,
},
{
text: "Piano",
value: 2,
},
{
text: "Tennis",
value: 2,
},
{
text: "Fitness",
value: 2,
},
{
text: "Psychology",
value: 1,
},
{
text: "Responsibility",
value: 1,
},
{
text: "Swimming",
value: 1,
},
{
text: "Philosophy",
value: 2,
},
{
text: "Creative writing",
value: 2,
},
{
text: "Entrepreneurship & leadership",
value: 2,
},
{
text: "Biking",
value: 2,
},
{
text: "Debate",
value: 1,
},
{
text: "Life skills",
value: 2,
},
{
text: "Badminton",
value: 1,
},
{
text: "Ultimate frisbee",
value: 1,
},
{
text: "Volleyball",
value: 1,
},
{
text: "Bodybuilding",
value: 3,
},
{
text: "Mindfulness",
value: 4,
},
{
text: "Self-regulation",
value: 1,
},
{
text: "Religion & Culture",
value: 2,
},
{
text: "Languages",
value: 3,
},
{
text: "Become a Youtuber",
value: 1,
},
{
text: "Drawing",
value: 1,
},
{
text: "Photography",
value: 1,
},
{
text: "Teaching",
value: 1,
},
{
text: "Dating",
value: 2,
},
{
text: "Have Sex",
value: 1,
},
{
text: "Board games",
value: 2,
},
{
text: "Music",
value: 2,
},
{
text: "Improved fashion",
value: 1,
},
{
text: "Cheerleading",
value: 1,
},
{
text: "Figure skating",
value: 1,
},
];

223
data/mocks.ts Normal file
View File

@ -0,0 +1,223 @@
/* Use this mock data to showcase your components in the playground,
* or add your own data that fits your component's props
*/
export const mockCategoricalData = [
{
category: "Roboto",
value: 88,
},
{
category: "Open Sans",
value: 16,
},
{
category: "Lato",
value: 14,
},
{
category: "Montserrat",
value: 73,
},
{
category: "Oswald",
value: 14,
},
{
category: "Source Sans Pro",
value: 8,
},
{
category: "Slabo 27px",
value: 41,
},
{
category: "Raleway",
value: 29,
},
];
export const mockPieData = [
{
category: "Nightingale",
value: 42,
},
{
category: "Quail",
value: 48,
},
{
category: "Cuckoo",
value: 10,
},
];
export const moreMockCategoricalData = [
{ key: "Python", value: 29.53 },
{ key: "Java", value: 17.06 },
{ key: "JavaScript", value: 8.56 },
{ key: "C", value: 6.49 },
{ key: "Assembly", value: 6.31 },
{ key: "R", value: 5.83 },
{ key: "Objective C", value: 4.43 },
{ key: "Swift", value: 3.89 },
{ key: "PHP", value: 3.85 },
{ key: "Rust", value: 3.33 },
{ key: "Ruby", value: 3.25 },
{ key: "Matlab", value: 3.06 },
{ key: "TypeScript", value: 3.98 },
{ key: "Go", value: 3.85 },
{ key: "Haskell", value: 3.28 },
{ key: "VBA", value: 3.11 },
{ key: "Scala", value: 2.79 },
{ key: "Lua", value: 2.79 },
{ key: "Julia", value: 2.77 },
{ key: "Kotlin", value: 2.7 },
{ key: "Perl", value: 2.41 },
{ key: "Groovy", value: 2.4 },
{ key: "Abap", value: 2.24 },
{ key: "Cobol", value: 2.23 },
{ key: "Ada", value: 2.21 },
{ key: "Dart", value: 2.21 },
];
export const mockStackedBarGraphData = [
{
category: "1A",
"geese watchers": 60,
"geese breeders": 80,
"geese catchers": 90,
},
{
category: "1B",
"geese watchers": 25,
"geese breeders": 37,
"geese catchers": 80,
},
{
category: "2A",
"geese watchers": 40,
"geese breeders": 50,
"geese catchers": 70,
},
{
category: "2B",
"geese watchers": 40,
"geese breeders": 80,
"geese catchers": 88,
},
{
category: "3A",
"geese watchers": 15,
"geese breeders": 30,
"geese catchers": 45,
},
];
export const mockStackedBarKeys = ["geese watchers", "geese breeders", "geese catchers"];
export const mockLineData = {
xValues: ["1A", "1B", "2A", "2B", "3A", "3B"],
lines: [
{
label: "Java",
yValues: [54, 88, 22, 66, 77, 88],
},
{
label: "C++",
yValues: [45, 22, 83, 98, 24, 33],
},
],
};
export const mockTimelineData = [
{
time: "Fall 2020",
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
},
{
time: "Winter 2021",
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad",
},
{
time: "Spring 2021",
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor i",
},
{
time: "Fall 2021",
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proid",
},
{
time: "Winter 2022",
text: "Lorem ipsum dolor sit amet, consectetur adipi",
},
{
time: "Spring 2022",
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut en",
},
];
export const mockBoxPlotData = [
{
category: "1A",
min: 20,
firstQuartile: 25,
median: 30,
thirdQuartile: 80,
max: 100,
outliers: [],
},
{
category: "1B",
min: 0,
firstQuartile: 20,
median: 30,
thirdQuartile: 50,
max: 100,
outliers: [],
},
{
category: "2A",
min: 25,
firstQuartile: 35,
median: 50,
thirdQuartile: 90,
max: 100,
outliers: [],
},
];
export const mockQuoteData = [
"The quick brown fox jumps over the lazy dog.",
"Sphinx of black quartz, judge my vow!",
"Pack my box with five dozen liquor jugs.",
];
export const mockQuoteDataLong = [
"Here, have some quotes of varying lengths, and see how they look.",
"Hello, world!",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla in enim neque. Sed sit amet convallis tellus. Integer condimentum a felis id gravida. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nullam metus libero, sagittis in consectetur in, scelerisque sed sapien. Nullam ut feugiat sapien. Praesent dictum ac ipsum ac lacinia.",
];
export const mockGroupedBarGraphData = [
{
category: "AJ",
values: {
Shooting: 7,
Melee: 9,
},
},
{
category: "Zen",
values: {
Shooting: 17,
Melee: 5,
},
},
{
category: "Lyra",
values: {
Shooting: 3,
Melee: 14,
},
},
];

430
data/personal.ts Normal file
View File

@ -0,0 +1,430 @@
export const P1 = [
"watonomous before it went remote",
"DanceDanceRevolution",
"Board games",
"orchestra@uWaterloo",
"Design Teams",
"WatLock",
"Playing in osu! tournaments as part of the osu! club.",
"I enjoyed doing art",
"SERVE tournaments",
"YuGiOh Club",
"Poker club",
"CS Club",
"MATH Residence Tutor",
"Volleyball drop in",
"Playing smash",
"CSC Karaoke <3",
"AcaBellas",
"Volleyball intramurals and drop-ins",
"mathNEWS",
"UWACC",
"mathNEWS, hands down. It's how I made most of my friends, and probably the thing I'm most likely to be remembered for.",
"Waterloo Ismaili Student Association",
"mathNEWS, 100%.",
"Jam Network",
"Weightlifting, powerlifting",
"Intramurals",
"Data Science Club",
"Imprint",
"Dance",
"Ultimate Frisbee",
"Testing freshly designed games at the game dev club.",
"Quidditch",
"Toastmasters",
"Muay Thai",
"Ultimate Frisbee Team",
"Volleyball",
"Badminton Club",
"Table tennis club",
"Limelight",
"Serve",
"Ultimate Frisbee, Hackathon Planning",
"Drag Club",
"Rock climbing.",
"Soccer intramurals",
"UWICA dance team",
"Volleyball intramurals",
"Humans VS Zombies",
"Camping",
"WaterBoys a capella",
"Taekwondo",
"Organizing Hack the North!",
"Chamber Choir",
];
export const P2 = [
"not a specific one, but not being an exec of a club",
"Game development",
"Volleyball",
"WiCS",
"Acapella",
"astronomy club",
"Ballroom dancing",
"CSC and Data Science Club",
"CSC",
"Kendo Club Ever",
"Band/orchestra",
"intramurals earlier",
"Blueprint",
"Animusic Ensembles",
"Formula SAE",
"powerlifting",
"Movie Watching Club",
"Ultimate Frisbee",
"Music, singing, band",
"Intramurals",
"poker club",
"Not quidditch lmao",
"Japan exchange",
"Joining any club.",
"Any philosophy courses?",
"Juggling",
"A capella",
"Badminton",
"Varsity Badminton",
"A long-term club or organization to stay committed to and get to know people well. Maybe outers club",
"A dance club of sorts",
"Hack the north",
"Humans vs Zombies",
"Dance crews",
"Animusic",
"GSA",
"UW esports team",
"UW HipHop",
"Basketball intramurals",
"I wish I didn't quite A capella club for a final.",
"Rizz club LMFAO",
];
export const P3 = [
"develop precise time estimation skills and abuse them to maximize free time",
"Learn mathematics and become enlightened",
"it doesn't matter how much you sleep, but when you sleep!",
"Don't think so hard!!",
"try everything at least once",
"Be the first person to apply for a job and your odds of getting it increase tenfold",
"Talk to other people about best coding practices",
"Life sucks at times, learn to embrace the bad times",
"You're usually fine in most situations",
"Sleep a lot",
"WW sucks -- apply externally!",
"Accept who you are and live with it.",
"Waterloo Star lunch special",
"Find and do something you enjoy when you are feeling down",
"Block out times for focus work!",
"Just hanging around the MC clubs hallway is a surprisingly good way to make friends.",
"Make friends with people who will get you out of your shell",
"Go to class",
"Submit a remark request for everything",
"Embrace mediocrity. Life is easier to cope with when you assume you're average. But life gets easier when you work towards improving yourself.",
"Meal prepping",
"go to costco",
"Switch out of morning courses and set your alarm as a timer for 8-9 hours of sleep.",
"simply start assignments early",
"Start early",
"Learn to cook, it's fun",
"Cook one big pot of soup, get those silicone soup molds and pour them in. Freeze em. Then when you need a meal quick, just pop a frozen soup cube out, microwave, you're done.",
"Keep organized using calendars and spreadsheets. It helped me to meet deadlines and to relieve stress by having a bird's eye view.",
"Sleep more",
"Learn ethics",
"Work-life balance",
"Anki flash cards. They're actually so strong for so many courses",
"Forcing yourself to get out of your apartment.",
"The key to sleeping early is to wake up early",
"Write notes on everything.",
"Be someone you'd want to be friends with",
"I think sleeping matters the most physically and mentally.",
"Vitamin D is the key to happiness, don't forget to take the supplements! Oh and stay hydrated.",
"No relationship",
"Take time to relax.",
];
export const P4 = [
"its not over until I win",
"every expert was once a beginner",
"try everything at least once",
'"The answer to the universe exists somewhere on the internet, you just need to go find it." -me',
"Any sufficiently advanced technology is indistinguishable from magic. Many things I once thought was magical have lost their magic when you learn about how they work. It's almost a beautiful thing really, coming into computer science and learning the ins and outs of computing to the point where technology stops to marvel you and instead you start to pick up on how things are built and created.",
"You do what you can, and where you can't, you can't.",
"Don't worry, be happy",
"Be yourself.",
"Patient: It hurts when I do this. Doctor: Then don't do that.",
"You've got to dig dee",
"For the experience",
"You're almost there",
"Letters to a Young Poet by Rilke",
"It's all about the mindset.",
"No one can make you feel inferior without your consent.",
'"It is possible to commit no mistakes and still lose. That is not a weakness, that is life." -Jean-Luc Picard',
"Live, love, laugh",
"The worst feeling is when the person you are meets the person you could've been",
"Don't be sad that it's over; be happy that it happened",
"Sometimes it do be like that",
"Born to shit, forced to wipe",
"Touch grass",
"An airplane always takes off against the wind",
'"Hesitation is defeat." - John Sekiro',
"Hard work is not your purpose of living.",
"Follow your own way and let people talk.",
"Live by no words.",
"It's our choices that show what we truly are, far more than our abilities.",
"The most important step to take is the next one.",
"Just Do It",
"Go big or go home",
];
export const P5 = [
"I fumbled a girl that wanted me first, twice o.o",
"I was at a party and knocked over their entire coat rack. The coats were everywhere :///",
"naked mile",
"Accidentally accepted a video call while naked in bed with gf",
"I was pulling an all nighter and was really sleep deprived I walked into the girls bathroom by accident.",
"Having to sit through a 45 minute technical interview when it was clear to both of us that I had no idea how to do the question",
"Probably the time i gave this girl a UTI because I didn't wash my hands properly. Wash your hands.",
"I played trumpet in mkv courtyard at 4am on what I thought was the day after the last day of exams but was actually the morning of the last day of exams",
"I don't want to say it.",
"Professor called me to answer a question in ENGL 306A, and I had no idea how to answer the question.",
"Holding hands with one of my friends and insisting it was platonic for several weeks before we started dating",
"I learned recently that the first person I ever went on a date with here really disliked how loudly I ate ramen, and that it's the only thing her group of friends know about me.",
"Confessing to a girl that I loved her while I was black out drunk",
"Accidentally pressed the fire alarm in the CMH gym, which was pretty crowded, in my first year",
"having a whole conversation with my roommate in first year while there was porn visibly on my computer screen",
"This girl asked me the 'what are we question' the day before Valentines day when I told her multiple times I wasn't ready for anything serious. I had to end the fling that day, felt like a total dick.",
"Think a janitor walked in on my bf and I about to kiss on one of our first dates when we were sitting in a classroom lol",
"I wasn't wearing glasses when meeting up with a friend and mistakenly thought that someone else was them.",
"I accidentally used the women's washroom in STC.",
"I failed PD1 by missing a single assignment",
"Being drunk and inviting my sober friend to a drinking party by baiting him with League of Legends.",
"Participating in sex toy bingo",
"Didn't know how to put on the graduation sash during convocation. There's probably more but I can't remember.",
"I choked on stage during a beatbox battle",
];
export const P6 = [
"complimented me (rare)",
"Ah so many, but one that was short and memorable was someone complemented my piano playing near the front of DP. That was when I was going through quite a rough time, and thanks to that person, my day was made much better and I also get to keep this memory :).",
"Tied my shoes",
"My second year roommate let me use his piano!",
"Admit me",
"Ask me to marry them",
"Let me take MATH 146 without taking MATH 135/145. A prof believed in me :)",
"Cooked me food :)",
"My girlfriend does a pretty good job of babying me when I start losing it/panicking over nothing",
"Let me crash at their place when I had in-person exams when I wasn't in person",
"Be friends with me",
"I left my stuff at a friend's place over Covid (I'm out of province), and I didn't grab it until 3 years later.",
"Agree to be my gf :)",
"One of my friends stayed up with me all night to help me finish an assignment",
"Complimented my sweater",
"I have quite a few examples but one that happened recently was two of my really good friends bought me comfort food (fried chicken), delivered it to my doorstep, at night, without asking, because I told them my grandma isn't doing so well.",
"A stranger tapped me on the shoulder and told me they liked my outfit.",
"A person chased me up because I droped my Watcard",
"firat year math advisor overriding me into a full math class despite being out-of-faculty",
"My friend just listened to me when I was having a breakdown about not doing well enough on my calculus final on campus (didn't do enough to meet that 60% bar). It meant the world to have someone else just empathize and tell me that retaking a course is not the end of the world.",
"Someone took a later bus so they could pick up my laptop charger for me.",
"Give me their cookie when I was crying in the library. Thank you kind sir I will never forget you.",
"2 professors let me write an exam on the weekend, after the rest of the class, because I was dealing with medical complications.",
"Given me a job",
"Stay with me at the hospital for my broken ankle for 3 hours.",
"Saying that I am the best random person they met in UW",
"Been my best friend",
"Staying up late to listen to me talk about my concerns.",
"Cheer me up when I was visibly upset.",
];
export const P7 = [
"Didn't attend more social events",
"Not going on an exchange term.",
"I wish I took the time to do a URA.",
"taking more courses i actually like",
"Not getting into Jane Street/HRT",
"Time went by so fast, I would love to be back in second year and get more time on campus and less remote studying.",
"Not taking more diverse CS courses",
"Not socializing more in first year",
"Not spending more time with friends in 1st/2nd year",
"Caring about marks for too long, and not socializing more earlier",
"Not taking trains.",
"Should have been more social",
"No exchange/coop term in Japan :(",
"Meet more people",
"Being in a relationship for the majority of the time.",
"I wish I didn't grind and stress that hard in first year about career. We're all going to make it :)",
"Going out and meeting new people/getting into a relationship sooner",
"Not doing exchange. I wish I prioritized exchange over getting more co-ops.",
"Not working harder to find a new grad job (we do be living in a tech recession)",
"I wish I had gotten more involved in campus life sooner. Once I did get involved, it really opened my social life.",
"I wish I did more co-op terms",
"Not participating more in the community",
"Didn't have a relationship",
"Skipping so many terms on campus because of coop and exchange",
"spending too much time on assignments in first and second year",
"Not doing an abroad term.",
"Didn't study in the first year",
"Not switching out of CS. I realized that I kind of hated CS in my first year; however, I was too afraid to make the switch.",
"Not researching more on which courses are worth taking.",
"Wish I went on EXCHANGE!!! Oh, and not studying harder for my Google APM intern interview :(",
"never got laid",
"Not meeting more people",
"Taking more courses that I personally was interested in - I kept getting talked into taking courses that I was not really interested in and was afraid of taking courses by myself for fear of getting low grades. After getting low grades in these courses and still succeeding, I realize that grades really don't matter that much and I should have learned what I was interested in.",
"Not having a relationship",
"drop the ego",
"Not socializing more and doing more extra-curricular activities",
"Losing touch with people during Covid",
"Didn't do enough terms on campus",
"Not trying harder",
"Not making better connections",
"I wish I spent more time making & maintaining friendships.",
"Not focusing more on the social aspects",
"Not being more active",
"not nailing down good study habits or health habits earlier",
"Losing touch with old friends",
"Attempting aggravated assault",
"Not doing more extracurricular activities.",
"Did not work hard enough in school",
"Wish I had taken the covid year off, feels like I didn't have enough time on campus.",
"Not making more friends",
"I didn't get to talk to more profs. They do know a lot of stuff.",
"Not spending more time with my friends and not dating : (",
"Didn't fully take a URA position",
"I wish I didn't work as hard. I wish I enjoyed life more.",
"Covid stole half my university experience.",
];
export const P8 = [
"grow your hair long so you stop looking 12 years old, hit the gym (dont be scared of not knowing what to do!)",
"After studying past a certain point, any further studying will only stress you out and will be counterproductive. It is important to take some rest and go hang out with friends more!",
"Make more of an effort in my first few terms to reach out and strengthen friendships/relationships.",
"apply to the jobs even if you don't think you'll get the job!",
"Chill out lmao",
"ur gay",
"There's no rush to make friends, find a girlfriend, or get a Cali job -- your main priority should be learning things outside of class",
"Believe in yourself",
"Take less PMATH and do more CS",
"Nothing, it would ruin the surprises that life has in store. It's like saying what do you wish you knew happened in a movie before watching it. Absolutely nothing.",
"Get out of your shell and go try new things!",
"Hang out more with the mutual friends",
"Spend more time studying and less time trying to get laid.",
"You'll do well -- put in the word and it will pay off",
"Go out and talk to people",
"Chill bro",
"Be more active at joining clubs and meeting new people",
"To take things slowly but also take more courses during the pandemic. Classes were so much easier then!",
"make lots of friends",
"Grades don't matter as much in uni, especially once you find a good coop",
"You're going to be OK.",
"Try new things",
"Join more clubs",
"Don't take courses with profs with bad reviews",
"Figure out how to study for finals",
"Itll be okay",
"You will achieve much more than you think.",
"Study plz",
"Switch out of CS and do Physics/Pure Math.",
"Struggle hard.",
"It's not always gonna feel like it's okay, but it's gonna be okay. Grades aren't everything, but",
"Apply for <jobs, opportunities, etc.> even if you don't think you'll qualify! Do more research in things you might be interested in. I missed a lot of opportunities by not being proactive.",
"Your hard work will pay off.",
"drop the ego",
"Make time for yourself so you don't burn out",
"It's a big change so don't be too hard on yourself",
"Leetcode",
"Make good connections and seek help for your mental health problems",
"It's not a waste",
"Take care of your physical and mental health!",
"You're doing good",
"Marks are fake, do leetcode",
"Talk with more people, spend less time in your room. It's more productive to make smart friends and become smart that way.",
"Have fun while it lasts",
"Talk to more people and don't care about what they think of you.",
"Go out there at focus on meeting new people and joining clubs",
"Focus more on learning to learn rather than grades",
"Make friends",
"The clock is ticking. The hours are going by. The past advances, the future recedes. Possibilities decrease, regrets mount. Do you understand, or will you choose to remain ignorant?",
"Don't put that much time solving other people's issue.",
"Take URA",
"Grades are not as important as you think. Take some internships off to travel on your own or chill with family.",
"Spend time getting better at things so you can be less insecure. Especially exercise.",
"Sleep more",
"Don't be afraid to quit things",
];
export const P9 = [
"if you want something you gotta ask for it",
"Things kinda just happen one way or another so you might as well go with the flow and try to make the best of things.",
"University is only good for purchasing a degree, to truly learn things you have to be self-taught",
"There is always someone better than you and everyone has different priorities in life. Compare yourself to your previous self and who you want to be. What other people choose can be inspirational, but worrying about doing less or worse isn't very constructive.",
"You can learn whatever you wish with the tools you've been given at UW",
"If you fail a course who cares. The most important things in life won't come from the courses you did badly on, because if you were truly interested and invested in that course, would you have failed?",
"No one thing should be your only focus, be that school, social life, a job.",
"Life isn't that serious",
"Math is fun!!!",
"There are always talented people here. Don't feel down just because you are ordinary.",
"Realize that sometimes you need to let things go and failing is an irreplaceable part of being successful.",
"That everything is fleeting. 4 month cycles really reminds you of that because once you settle into a new home, new roommate situation, new city - everything changes again in just a few short months. Take the time to turn your 4 month house into a home. The goodbyes are painful but so worth it to look back upon each term with fond memories.",
"Get out of the house.",
"Look out for yourself and yourself alone",
"That I'm average in almost every single aspect and there is no use in assume your better than anyone or anything. I'm on a constant journey of learning new stuff. Not necessarily academic but soft skills too.",
"procrastination is easy to overcome if you understand the value of the work you are doing",
"People are much dumber than you think they are",
"You get what you give",
"Your dreams lie far beyond here. Keep looking forward.",
"Self-acceptance and how to embrace failures as much as your successes",
"drop the ego",
"Time flies, so act now instead of tomorrow",
"Bad code that works is better than good code that doesn't work",
"Live in the present moment",
"Marks are fake",
"You're not alone, but you're are the one that cares most about your career by a long shot",
"Networking and connections matter.",
"What happened has happened, what matters is what happens next",
"Life is a marathon, not a sprint",
"How to curl my hair",
"Plan before you do.",
"Don't be too harsh on yourself, a lot of things are based on luck. Accept your failures and keep reaching for your goals.",
"Success is built from daily effort.",
"Don't try to plan ahead too much!",
];
export const P10 = [
"finishing trains!",
"Living in downtown Toronto during my first co-op was pretty sick. Close second is all of the orchestra concerts.",
"Meeting my gf",
"All the great times I had with my friends",
"Walking around in springtime near the nanotechnology building",
"Living with my best friends at the Hub in the summer",
"Going to my first party in 4B and just getting fucked up - or nude dude event",
"Probably getting drunk with friends at a party",
"Late nights in mkv doing advanced courses",
"Might be my convocation day?",
"All my friends gathered together to hear me read a chapter from a story I was writing.",
"Singing with friends",
"Performing with the Water Boys at the International Championship of Collegiate A Cappella! We got 3rd place :')",
"My girlfriend coming to visit me while I was on co-op in California.",
"Drinking in class during St.Patties",
"San Francisco",
"It was when I got an email from a really cool company that I'd gotten an offer as an intern. Also, when I told my parents about this news, in-person, and seeing the smiles on their faces. Nothing matches seeing my parents happy.",
"friends <3",
"Late night talks and deep conversations",
"My friends",
"walking home from my CS246 demo on a beautiful December morning, having aced the project that had consumed the entire last two weeks of my life",
"Nights staying in and drinking with my roomates.",
"It's hard to find the favorite :)",
"Just getting boba and takeout with friends and eating together on the fifth floor of E7.",
"many final year friends",
"Having potlucks, playing board games, and going on trips with friends",
"Ppl sleeping on my floor",
"Math in Europe",
"Coops and exchange",
"3AM Burger King runs",
"Late nights in MH with friends, or in SF",
"Laughing together on the floor of Rev after a night out",
"Chilling with the boys in WCRI Fenwick, watching anime.",
"Reading week snowboard trip to Mont Tremblant",
"Hanging out with my friends in residence",
"Eating a cupcake I bought from the V1 cafeteria alone in my dorm room on my birthday while listening to Hatsune Miku songs through $8 earbuds from Amazon.",
"None",
"Playing piano with friends back in first year when things were fresh and everyone was still together.",
"Playing board games with friends late into the night.",
"Getting great coop job",
];

27
data/post-grad.ts Normal file
View File

@ -0,0 +1,27 @@
export const P1 = [
{ category: "PhD + Masters", value: 5 },
{ category: "PhD", value: 6 },
{ category: "Masters", value: 16 },
{ category: "Not sure", value: 39 },
{ category: "No", value: 67 },
];
export const P2 = [
{ category: "Some", value: 55 },
{ category: "Half", value: 31 },
{ category: "Most", value: 42 },
{ category: "All", value: 3 },
];
export const P3 = [
{ category: "1", value: 6 },
{ category: "2", value: 9 },
{ category: "3", value: 6 },
{ category: "4-8", value: 21 },
{ category: "9+", value: 14 },
];
export const P4 = [
{ category: "Yes", value: 89 },
{ category: "No", value: 37 },
];

70
data/routes.ts Normal file
View File

@ -0,0 +1,70 @@
export interface PageRoute {
name: string;
url: string;
}
type PageID =
| "home"
| "demographics"
| "academics"
| "computerScienceExperience"
| "coop"
| "lifestyleAndInterests"
| "intimacyAndDrugs"
| "postGrad"
| "fullTime"
| "mentalHealth"
| "personal"
| "contributors";
export type PageRoutes = { [key in PageID]: PageRoute };
export const pageRoutes: PageRoutes = {
home: {
name: "Home",
url: "/",
},
demographics: {
name: "Demographics",
url: "/demographics",
},
academics: {
name: "Academics",
url: "/academics",
},
computerScienceExperience: {
name: "CS Experience",
url: "/computer-science-experience",
},
coop: {
name: "Co-op",
url: "/coop",
},
lifestyleAndInterests: {
name: "Lifestyle and Interests",
url: "/lifestyle-and-interests",
},
intimacyAndDrugs: {
name: "Intimacy and Drugs",
url: "/intimacy-and-drugs",
},
postGrad: {
name: "Post-grad",
url: "/post-grad",
},
fullTime: {
name: "Full-time",
url: "/full-time",
},
mentalHealth: {
name: "Mental Health",
url: "/mental-health",
},
personal: {
name: "Personal",
url: "/personal",
},
contributors: {
name: "Contributors",
url: "/contributors",
},
};

27
deploy.sh Normal file
View File

@ -0,0 +1,27 @@
#!/usr/bin/env bash
set -ex
ulimit -u 512
DIR=$(mktemp --directory)
trap "rm -rf $DIR" EXIT
pushd $DIR
git clone file:///srv/git/www/class-profile-2023.git --depth=1
cd class-profile-2023
export NEXT_PUBLIC_BASE_PATH="/classprofile/2023"
npm ci
npm run build
npm run export
chgrp -R www out
chmod -R g+w out
shopt -s dotglob
rm -rf /srv/classprofile/2023/*
mv out/* /srv/classprofile/2023/
popd

10
next.config.js Normal file
View File

@ -0,0 +1,10 @@
const basePath = process.env.NEXT_PUBLIC_BASE_PATH || "";
/** @type {import('next').NextConfig} */
const nextConfig = {
basePath,
assetPrefix: `${basePath}/`,
publicRuntimeConfig: { basePath },
};
module.exports = nextConfig;

4586
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

45
package.json Normal file
View File

@ -0,0 +1,45 @@
{
"name": "class-profile-2023",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"preview": "bun run build && bun start",
"lint": "eslint \"{app,components}/**/*.{js,ts,jsx,tsx}\"",
"lint:fix": "eslint \"{app,components}/**/*.{js,ts,jsx,tsx}\" --fix"
},
"dependencies": {
"@uidotdev/usehooks": "^2.4.1",
"@visx/axis": "^3.5.0",
"@visx/event": "^3.3.0",
"@visx/grid": "^3.5.0",
"@visx/group": "^3.3.0",
"@visx/legend": "^3.5.0",
"@visx/mock-data": "^3.3.0",
"@visx/scale": "^3.5.0",
"@visx/shape": "^3.5.0",
"@visx/stats": "^3.5.0",
"@visx/text": "^3.3.0",
"@visx/tooltip": "^3.3.0",
"@visx/wordcloud": "^3.3.0",
"next": "14.0.3",
"react": "^18",
"react-dom": "^18"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"@typescript-eslint/eslint-plugin": "^6.11.0",
"@typescript-eslint/parser": "^6.11.0",
"eslint": "^8",
"eslint-config-next": "14.0.3",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-unused-imports": "^3.0.0",
"prettier": "^3.1.0",
"typescript": "^5"
}
}

Binary file not shown.

View File

@ -0,0 +1,20 @@
<svg width="351" height="594" viewBox="0 0 351 594" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M689.51 333.926C641.582 519.358 451.013 630.468 263.864 582.096C76.7146 533.724 -36.1465 344.188 11.7817 158.755C59.71 -26.6773 250.278 -137.787 437.427 -89.4147C624.577 -41.0427 737.438 148.493 689.51 333.926Z"
fill="url(#paint0_linear_7_1598)"
/>
<path
d="M689.51 333.926C641.582 519.358 451.013 630.468 263.864 582.096C76.7146 533.724 -36.1465 344.188 11.7817 158.755C59.71 -26.6773 250.278 -137.787 437.427 -89.4147C624.577 -41.0427 737.438 148.493 689.51 333.926Z"
fill="url(#paint1_linear_7_1598)"
/>
<defs>
<linearGradient id="paint0_linear_7_1598" x1="349.66" y1="133.643" x2="696.617" y2="728.723" gradientUnits="userSpaceOnUse">
<stop stop-color="#FAA3BD" stop-opacity="0.996875" />
<stop offset="1" stop-color="white" stop-opacity="0" />
</linearGradient>
<linearGradient id="paint1_linear_7_1598" x1="349.66" y1="133.643" x2="696.617" y2="728.723" gradientUnits="userSpaceOnUse">
<stop stop-color="#FFF0BB" stop-opacity="0.996875" />
<stop offset="1" stop-color="white" stop-opacity="0" />
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

Some files were not shown because too many files have changed in this diff Show More