27 |
28 | {% if page.image %}
29 |
30 | {% endif %}
31 | {{ content }}
32 |
33 | More blog posts
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CSHPublicSite - [csh.rit.edu](https://csh.rit.edu)
2 |
3 | The public facing website for [Rochester Institute of Technology](https://rit.edu/)'s [Computer Science House](https://csh.rit.edu).
4 |
5 | ## Overview
6 |
7 | This site is written using [Jekyll](https://jekyllrb.com/), a static site generator built with Ruby, and uses Sass and JavaScript ES6.
8 |
9 | ## Local Development
10 |
11 | Build the container: `docker build -t cshpublicsite .`
12 | Run the container: `docker run -p 4000:80 cshpublicsite`
13 | You will be able to access the site at http://localhost:4000.
14 |
15 | You can either edit files in the container, or rebuild the container when you want to test changes.
16 |
17 | ## Contributing
18 |
19 | 1. [Fork](https://help.github.com/en/articles/fork-a-repo) this repository
20 | - Create a new [git branch](https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell) if your change is more than a small tweak (`git checkout -b BRANCH-NAME-HERE`)
21 | 3. Make your changes locally, commit, and push to your fork
22 | 4. Create a [Pull Request](https://help.github.com/en/articles/about-pull-requests) on this repo for our Webmasters to review
23 |
24 | ## Questions/Concerns
25 |
26 | Please file an [Issue](https://github.com/ComputerScienceHouse/CSHPublicSite/issues/new) on this repository or contact [webmaster@csh.rit.edu](mailto:webmaster@csh.rit.edu) with inquiries about the site.
27 |
--------------------------------------------------------------------------------
/_includes/post.html:
--------------------------------------------------------------------------------
1 | {% if include.post %}
2 | {% assign post = include.post %}
3 | {% assign image = "/logo_background.png" | prepend: site.env.CSHPUBSITE_ASSETS_URL %}
4 | {% if post.image %}
5 | {% assign image = post.image | prepend: site.env.CSHPUBSITE_ASSETS_URL %}
6 | {% else %}
7 | {% assign hash = post.title | md5 | regex_replace: '[^\d]', '' %}
8 | {% endif %}
9 |
31 | Though the walls are the same as regular dorm rooms, our rooms usually look rather different than the standard RIT room layout.
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/_posts/2017-11-03-suds.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: SUDS
4 | date: 2017-11-2
5 | categories:
6 | - projects
7 | description: Shower Use Detection System
8 | author: Seth Gower
9 | author-image: https://avatars3.githubusercontent.com/u/19225089
10 | author-bio: First year Computer Engineering student
11 | author-email: seth@sethgower.com
12 | author-social:
13 | github: https://github.com/SethGower
14 | linkedin: https://www.linkedin.com/in/sethgower/
15 | ---
16 | [SUDS](https://github.com/sethgower/suds), or the Shower Use Detection System, shows the status of the showers in our dorm hall, which is located on the third floor of Fredericka Douglass Sprague Perry Hall. When someone is in the shower and the door is locked, an LED on a panel in the hall next to the bathroom illuminates. In addition to the LEDs outside of the bathroom, I will be creating a web app to track live status updates remotely, and potentially collect statistics on when the showers/stalls are most used.
17 |
18 | SUDS is the first big hardware project that I have ever actually done, and the first time I have soldered my own board (outside of soldering headers onto MCUs and chips). The web app that I am going to build will be my first time using a MySQL database and creating a server-side backend that handles all of the input from the bathrooms.
19 |
20 | SUDS is a project that was first created by CSHers a few years ago. It was originally a simple circuit driven by AA batteries, but my version runs on a Raspberry Pi.
21 |
22 | SUDS is driven by a Raspberry Pi in the bathroom ceiling, which outputs 5V; for future versions I will be making the circuit draw 3.3V to decrease the brightness of the LEDs. The current then goes to a limit switch on the door lock which closes the circuit and illuminates the LED for that shower. The wiring diagrams can be found on the [GitHub page](https://github.com/sethgower/suds). On the proto-board, on the same row as the anode of the LED, there is a pulldown resistor that leads to the GPIO pin corresponding to that shower.
23 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # require 'html-proofer'
2 |
3 | # Add environment variables below
4 | envvars = {
5 | CSHPUBSITE_ASSETS_URL: "https://assets.csh.rit.edu/pubsite",
6 | CSHPUBSITE_S3_URL: "https://s3.csh.rit.edu"
7 | }.map { |k,v| ["#{k}=#{v}"]}.join(" ")
8 |
9 | $outputDir = "./_site"
10 | $testOpts = {
11 | # An array of Strings containing domains that will be treated as internal urls
12 | :internal_domains => ["pubsite.a.csh.rit.edu"],
13 | # Ignore errors "linking to internal hash # that does not exist"
14 | :url_ignore => ["#"],
15 | # Allow empty alt tags (e.g. alt="") as these represent presentational images
16 | :empty_alt_ignore => true,
17 | # Automatically add extension (e.g. .html) to file paths, to allow extensionless URLs
18 | :assume_extension => true,
19 | # LinkedIn blocks connections from html-proofer, ignore 999 error
20 | :http_status_ignore => [999],
21 | # SSL seems to be broken on TravisCI, so we'll ignore SSL errors.
22 | :typhoeus => {
23 | :ssl_verifypeer => 0,
24 | :ssl_verifyhost => 0,
25 | }
26 | }
27 |
28 | task :default => ["serve:development"]
29 |
30 | desc "cleans the output directory"
31 | task :clean do
32 | sh "jekyll clean"
33 | end
34 |
35 | namespace :build do
36 |
37 | desc "build development site"
38 | task :development => [:clean] do
39 | sh "#{envvars} jekyll build --drafts"
40 | end
41 |
42 | desc "build production site"
43 | task :production => [:clean] do
44 | sh "#{envvars} JEKYLL_ENV=production jekyll build --config=_config.yml"
45 | end
46 | end
47 |
48 | namespace :serve do
49 |
50 | desc "serve development site"
51 | task :development => [:clean] do
52 | sh "#{envvars} jekyll serve --drafts"
53 | end
54 |
55 | desc "serve production site"
56 | task :production => [:clean] do
57 | sh "#{envvars} JEKYLL_ENV=production jekyll serve --config=_config.yml"
58 | end
59 | end
60 |
61 | # desc "test production build"
62 | # task :test => ["build:production"] do
63 | # HTMLProofer.check_directory($outputDir, $testOpts).run
64 | # end
65 |
--------------------------------------------------------------------------------
/membership/insights.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: page
3 | title: Insights
4 | active: membership-insights
5 | ---
6 |
7 |
8 |
9 |
10 |
11 |
Accepted Student Open House
12 |
April 7-8, 2018
13 |
14 |
ImagineRIT Weekend
15 |
April 27-28, 2018
16 |
17 |
18 |
19 |
20 |
21 | Insights is a promotional program where prospective students have the option to spend a weekend at Computer Science House. As the name would suggest, Insights gives students a real, first-hand experience of campus life the likes of which no tour guide can convey. Students will spend a weekend hosted by members of CSH, a Special Interest Floor dedicated to students interested in computing. They will have to opportunity to participate in learning workshops hosted by house members, join in on CSH traditions like Capture the Disk, and much more.
22 |
23 |
24 | Available spots for Insights will be given out on a first come first serve basis. Also, your interest and possible participation in Insights in no way effects your application to or evaluations process in Computer Science House.
25 |
35 |
--------------------------------------------------------------------------------
/_posts/2017-11-02-audiophiler.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: Creating Audiophiler
4 | date: 2017-11-02 21:25:00
5 | categories: projects
6 | description: Audiophiler, a neat python web app for serving music
7 | author: Stephen Greene
8 | image: /projects/Audiophiler.png
9 | image-sm: /projects/Audiophiler.png
10 | author-image: https://avatars0.githubusercontent.com/u/17414243?s=460&v=4
11 | author-bio: Second Year Computer Science Student at Rochester Institute of Technology and a System Administrator for CSH as well as KGCOE
12 | author-email: purple@csh.rit.edu
13 | author-social:
14 | github: https://github.com/sgreene570
15 | ---
16 | [Audiophiler](https://github.com/sgreene570/audiophiler) is a Python Flask web app that serves audio files.
17 | Audiophiler uses CSH's Ceph storage cluster to hold audio files and serves them through an easy to use API.
18 | The Audiophiler API allows other house services to quickly retrieve a member's uploaded audio files.
19 | When members come off of the DSP elevators and walk onto floor, they can tap their iButton against one of the
20 | readers in the elevator lobby to load up songs on Audiophiler and play them aloud.
21 |
22 | Audiophiler is the first web app that I've written entirely by myself. While working on the project, I learned _a lot_ about
23 | writing code for the web. Within my web app, I leverage a Postgres database to store audio file information. I also use
24 | CSH's Ceph environment to hand out links to audio files, allowing for very fast file retrieval.
25 |
26 | Audiophiler went through many changes before I passed it as a major project, and is still being worked on now. In my opinion, Audiophiler is a great example of what CSH computer resources are capable of. The CSH OpenShift cluster lets me "deploy" my web app to the internet without any hassle.
27 |
28 | In the future, I plan on cleaning up and optimizing Audiophiler. Recently, I have gotten some other CSHers to help me tweak my web app and offer feedback.
29 | I look forward to working with more people on my project and creating something that house members will use for a while.
30 |
--------------------------------------------------------------------------------
/_posts/2018-01-22-alexa-rss-skill-and-companion-web-app.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: Alexa RSS Skill
4 | date: 2018-01-22
5 | categories:
6 | - projects
7 | description: Alexa Skill that reads out tags from an RSS Feed
8 | image:
9 | image-sm:
10 | author: Fred Rybin
11 | author-image: https://avatars0.githubusercontent.com/u/17693407?s=460&v=4
12 | author-bio: First Year Computing Security student
13 | author-email: fredrybin@gmail.com
14 | author-social:
15 | github: https://github.com/frybin
16 | linkedin: https://www.linkedin.com/in/frybin/
17 | ---
18 |
19 | The [Alexa RSS Skill](https://github.com/frybin/Alexa-RSS-Skill) is an Alexa skill, which is an app for Amazon's Alexa platform, that reads content in tags from an RSS Feed. It works by asking the user for an input for which RSS Feed they would like hear and then from the user's input it reads out the appropriate feed. The data for the different feeds like that name and links to the feeds are all stored in MySQL. Due to the skill needing to pull information from a database, I decided to make a companion web app to go with it. The [RSS Companion App](https://github.com/frybin/RSS-Web-App) is a simple Python Flask web app that connects to the same MySQL database as the Alexa skill and lets the user add, edit, and delete RSS feeds from the database.
20 |
21 | The Alexa RSS Skill and its companion app is the first big coding project that I have ever made. When I first started on this project, I had very little coding experience and had no knowledge on how Amazon Alexa and AWS Lambda worked. While working on this project I had learned how to use Git, GitHub, Node.js, Amazon AWS, and Python Flask. The skill went through many iterations until I finally understood how Amazon AWS Lambda and the Alexa Skill Builder worked and communicated with each other.
22 |
23 | All in all, I found this project enjoyable and it was a great learning experience. Though I am finished with this project, I plan to try to make another Alexa skill using another coding language like Python. Although I might now know the basics about making a skill, I could learn something new and have more fun troubleshooting through the problems that arise in coding projects.
24 |
25 | You can see the all of the source for the Alexa Skill [here](https://github.com/frybin/Alexa-RSS-Skill) and for the web app [here](https://github.com/frybin/RSS-Web-App).
26 |
--------------------------------------------------------------------------------
/_posts/2018-04-30-resume-review.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | permalink: /:categories/:title:output_ext
4 | title: Resume Review
5 | date: 2018-04-30
6 | categories:
7 | - projects
8 | description: A webapp to upload resumes and review those of your peers
9 | image: /projects/resume.png
10 | image-sm: /projects/resume.png
11 | author: Ram Zallan
12 | author-image: https://avatars3.githubusercontent.com/u/5818258
13 | author-bio: Second year Computer Science major, full stack software engineer. ramzallan.me
14 | author-email: ram@csh.rit.edu
15 | author-social:
16 | github: https://github.com/ramzallan
17 | linkedin: https://linkedin.com/in/ramzallan
18 | ---
19 |
20 | ### Overview
21 | [Resume Review](https://resumes.csh.rit.edu) is a web app written for CSHers to upload their resumes and receive feedback on them.
22 | Members can prepare for career fairs, company visits, and job applications by running their resumes by their peers, requesting specific changes or just asking for general opinions.
23 |
24 | The site allows for the upload of PDF files, and [reinforces good file naming practices](https://github.com/RamZallan/resume-review/blob/d3ca7f68bf940e5aeaea42061b5278369b89a90d/routes/upload.js#L29).
25 | Members can comment on posts, and comments can be threaded to allow for direct responses to feedback.
26 | Once posted, users can leave comments on their own resumes to act as a description, if they want to denote things like past versions, recent changes, etc.
27 | Members can also delete their own resumes or comments if they choose to.
28 |
29 | 
30 |
31 | The homepage shows a list of recently posted resumes, so users can browse through people looking for review on their resumes.
32 |
33 |
34 | ### Technical Details
35 | Resume Review is the first project that I've made using [Express](https://expressjs.com/), a Node.js framework.
36 | It runs on CSH's OpenShift Origin cluster, and uses our internal S3 to store files.
37 | The site uses a PostgreSQL database for storing resume metadata and comments.
38 | It's also the first Node.js project to use CSH's OpenID Connect authentication.
39 |
40 | Resume Review can be found at [resumes.csh.rit.edu](https://resumes.csh.rit.edu), and even though the site itself is behind CSH authentication, its source code is open source on [GitHub](https://github.com/ramzallan/resume-review/).
41 |
--------------------------------------------------------------------------------
/_posts/2017-11-27-soft-calendar.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: Soft Calendar
4 | date: 2017-11-27
5 | categories:
6 | - projects
7 | description: A Calendar Event Manager!
8 | image: /projects/softCalendar.jpg
9 | image-sm: /projects/softCalendar.jpg
10 | author: Skyler Clark
11 | author-image: https://avatars0.githubusercontent.com/u/4897492?s=400&v=4
12 | author-bio: A freshman computer science student!
13 | author-email: sjc1689@rit.edu
14 | author-social:
15 | github: https://github.com/SkylerJaneClark
16 | linkedin: https://www.linkedin.com/in/skyler-c-58962012b/
17 | ---
18 | Soft calendar is an Android app that helps keep Google Calendars clean and organized, making an easy to view checklist of events and their due dates. It is integrated with Google Calendar, so when you want to commit to an event, just select it from the list and push it to your calendar!
19 |
20 | Soft calendar was the first Android app I’ve ever built, and with it came a lot of challenges. In all honesty, I would say that the hardest step was configuring my development environment, and learning about how Android Studio worked. After that, I had to learn about how the Google Calendar API worked, how authentication worked, how to pass data through forms, how to save user input, (and fix all of the bugs that naturally crop up along the way when you have no idea what you’re doing!)
21 |
22 | I came up with the idea during my first week or so of school, when there were a ton of things to do all happening at the same time, and I was a little overwhelmed. My soft calendar idea was so I could make a visual representation of the things I wanted to do without having to clutter my Google Calendar with things that I may or may not end up at. The irony is that coding the soft calendar actually ended up taking up all my time, as opposed to going places, rendering the whole thing pretty counterintuitive!
23 |
24 | But all things considered, working on an Android app really taught me a lot about how to work on (and finish!) a project instead of just going halfway and leaving it unfinished forever. Though I wouldn’t recommend working on an Android app as a first project, it was really a worthwhile experience regardless. You can see all of the source on my [GitHub page](https://github.com/SkylerJaneClark/softCalendar) If you think it’s cool, or that you could use something like this in your life, you can download it right onto your phone from the [releases](https://github.com/SkylerJaneClark/softCalendar/releases)
25 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | addressable (2.8.0)
5 | public_suffix (>= 2.0.2, < 5.0)
6 | colorator (1.1.0)
7 | concurrent-ruby (1.1.10)
8 | em-websocket (0.5.3)
9 | eventmachine (>= 0.12.9)
10 | http_parser.rb (~> 0)
11 | eventmachine (1.2.7)
12 | ffi (1.15.5)
13 | forwardable-extended (2.6.0)
14 | http_parser.rb (0.8.0)
15 | i18n (1.10.0)
16 | concurrent-ruby (~> 1.0)
17 | jekyll (4.2.2)
18 | addressable (~> 2.4)
19 | colorator (~> 1.0)
20 | em-websocket (~> 0.5)
21 | i18n (~> 1.0)
22 | jekyll-sass-converter (~> 2.0)
23 | jekyll-watch (~> 2.0)
24 | kramdown (~> 2.3)
25 | kramdown-parser-gfm (~> 1.0)
26 | liquid (~> 4.0)
27 | mercenary (~> 0.4.0)
28 | pathutil (~> 0.9)
29 | rouge (~> 3.0)
30 | safe_yaml (~> 1.0)
31 | terminal-table (~> 2.0)
32 | jekyll-environment-variables (1.0.1)
33 | jekyll (>= 3.0, < 5.x)
34 | jekyll-feed (0.16.0)
35 | jekyll (>= 3.7, < 5.0)
36 | jekyll-regex-replace (1.1.0)
37 | jekyll-sass-converter (2.2.0)
38 | sassc (> 2.0.1, < 3.0)
39 | jekyll-seo-tag (2.8.0)
40 | jekyll (>= 3.8, < 5.0)
41 | jekyll-watch (2.2.1)
42 | listen (~> 3.0)
43 | kramdown (2.4.0)
44 | rexml
45 | kramdown-parser-gfm (1.1.0)
46 | kramdown (~> 2.0)
47 | liquid (4.0.3)
48 | liquid-md5 (0.0.3)
49 | liquid (>= 2.5, < 5.0)
50 | listen (3.7.1)
51 | rb-fsevent (~> 0.10, >= 0.10.3)
52 | rb-inotify (~> 0.9, >= 0.9.10)
53 | mercenary (0.4.0)
54 | minima (2.5.1)
55 | jekyll (>= 3.5, < 5.0)
56 | jekyll-feed (~> 0.9)
57 | jekyll-seo-tag (~> 2.1)
58 | pathutil (0.16.2)
59 | forwardable-extended (~> 2.6)
60 | public_suffix (4.0.7)
61 | rake (12.3.3)
62 | rb-fsevent (0.11.1)
63 | rb-inotify (0.10.1)
64 | ffi (~> 1.0)
65 | rexml (3.2.5)
66 | rouge (3.29.0)
67 | safe_yaml (1.0.5)
68 | sassc (2.4.0)
69 | ffi (~> 1.9)
70 | terminal-table (2.0.0)
71 | unicode-display_width (~> 1.1, >= 1.1.1)
72 | unicode-display_width (1.8.0)
73 | webrick (1.7.0)
74 |
75 | PLATFORMS
76 | x86_64-linux
77 |
78 | DEPENDENCIES
79 | jekyll
80 | jekyll-environment-variables
81 | jekyll-feed (~> 0.6)
82 | jekyll-regex-replace
83 | liquid-md5
84 | minima (~> 2.5)
85 | rake (~> 12.3)
86 | tzinfo-data
87 | webrick
88 |
89 | BUNDLED WITH
90 | 2.3.17
91 |
--------------------------------------------------------------------------------
/_posts/2018-04-12-oneshot-character-generator.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: One Shot Character Generator
4 | date: 2018-04-12
5 | categories:
6 | - projects
7 | description: D&D Character Generator
8 | author: Kevin Schwenk
9 | author-bio: Second year CS major
10 | author-email: kss3800@rit.edu
11 | author-social:
12 | github: https://github.com/mouseexe
13 | website: http://kevinschwenk.com
14 | ---
15 | ## Why it exists:
16 |
17 | I play in a lot of D&D one shot sessions, and I was sick and tired of wasting brain cells on character ideas I would only use for about 6 hours and then never again. This website will roll stats, select a race, and finally a class with subclass for you, all at the click of a button.
18 |
19 | ## How it's built:
20 |
21 | I used a Python backend to roll stats and select optimal character options. I used Flask to integrate my backend with a simple HTML page and simple CSS to make it a bit prettier. I used a modified version of the Colville character generation method, which involves rolling 4d6 dropping the lowest 6 times, and using each roll down the line of stats (Strength first, then Dexterity, and so on). After the stats have been rolled, it looks at the two highest stats and assigns a race based on those. Finally, it again compares the stats to pick a class well suited to the current character.
22 |
23 | ## Challenges it presented:
24 |
25 | Before I started this project, I was unfamiliar with web development, so that was a big learning experience. The longer I worked on the website, the more comfortable I felt with making changes and improving the design. On the back end, I encountered an issue with code readability when I tried to automatically select a race for the player. Python doesn't have switch statements, so I had to make something similar using a Python dictionary. The project was relatively straightforward once I solved the initial web issues and the switch problem, and was more focused on adding in new features.
26 |
27 | ## What could be redone:
28 |
29 | I had to use a Python dictionary as a form of "pseudo-switch," which feels wrong to me. I can't find a better solution that doesn't involve a complex series of conditionals. I'd like to refactor the code to be a lot cleaner overall, and I plan on doing so over the summer. I also plan on adding in random background generation, and potentially automatic backstory details as well.
30 |
31 | [Create a character](http://charactergen.win)
32 |
33 | [View the code](https://github.com/mouseexe/OneShotCharacterGenerator)
34 |
--------------------------------------------------------------------------------
/_sass/_nav.scss:
--------------------------------------------------------------------------------
1 | // override csh-material-bootstrap
2 | .navbar {
3 | position: fixed;
4 | top: 0;
5 | left: 0;
6 | z-index: 99;
7 | box-shadow: none;
8 | width: 100%;
9 | background: rgba(0, 0, 0, 0.6);
10 | padding: 0.25em 0.5em;
11 | }
12 |
13 | nav {
14 | & .navbar-brand {
15 | transition: 0.4s max-height, 0.4s margin;
16 | max-height: 100px;
17 | padding-top: 15px;
18 | padding-bottom: 15px;
19 | margin: 10px 0;
20 | background-image: url('#{$CSHPUBSITE_ASSETS_URL}/csh_logo_square.svg');
21 | background-repeat: no-repeat;
22 | background-size: contain;
23 | background-position: left center;
24 | }
25 | & img {
26 | display: inline;
27 | }
28 |
29 | & ul {
30 | list-style-type: none;
31 | display: inline;
32 | padding: 0;
33 | & li {
34 | display: inline-block;
35 | padding: 5px 10px;
36 | font-size: 0.75em;
37 | font-weight: 600;
38 | text-transform: uppercase;
39 | }
40 | & a {
41 | color: white;
42 | letter-spacing: 1px;
43 | padding: 2px 0;
44 | border-bottom: 3px solid transparent;
45 | transition: 0.4s border-color;
46 | &:hover {
47 | text-decoration: none;
48 | color: lighten($csh-pink, 50%);
49 | border-color: lighten($csh-pink, 50%);
50 | }
51 | &.active,
52 | &:active {
53 | border-color: lighten($csh-pink, 30%);
54 | }
55 | }
56 | }
57 | & .dropdown-menu {
58 | min-width: 170px;
59 | width: auto;
60 | padding: 10px;
61 | background: rgba(0, 0, 0, 0.6);
62 | & li {
63 | display: block;
64 | }
65 | }
66 | .dropdown:hover .dropdown-menu {
67 | display: block;
68 | }
69 | &.condensed {
70 | .navbar-brand {
71 | max-height: 40px;
72 | margin: 5px 0;
73 | }
74 | & .dropdown-menu {
75 | font-size: 1.2em;
76 | }
77 | }
78 | @media(max-width: 992px) {
79 | .navbar-brand {
80 | max-height: 50px;
81 | }
82 | .navbar-toggler-icon {
83 | width: 30px;
84 | height: 30px;
85 | }
86 | }
87 | }
88 |
89 | .btn.dropdown-toggle:before {
90 | display: none; // remove beginning caret for dropdowns
91 | }
92 |
--------------------------------------------------------------------------------
/_includes/footer.html:
--------------------------------------------------------------------------------
1 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/_posts/2017-12-27-deepnet-synapse-delta-visualizer.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: Deepnet Synapse Delta Visualizer
4 | date: 2017-12-27
5 | categories:
6 | - projects
7 | description: Four Layer Deep-Learning Neural Network with OpenGL Visualization
8 | image: /projects/neuralNetwork.png
9 | image-sm: /projects/neuralNetwork.png
10 | author: Jacob Potter
11 | author-image: https://csh.rit.edu/~jpotter/jpotter.jpg
12 | author-bio: Second year Computer Science major.
13 | author-email: jmp1617@rit.edu
14 | author-social:
15 | github: https://github.com/jmp1617
16 | linkedin: https://www.linkedin.com/in/jacob-potter-325754129/
17 | ---
18 | This project involves the use of a simple four layer deep-learning neural network written in C that I built from scratch which leverages the [sigmoid](https://en.wikipedia.org/wiki/Sigmoid_function) activation function along with [backpropagation](https://en.wikipedia.org/wiki/Backpropagation) to assist previous layers with correction. The option for variable size and count of the training data allows for the network to optimally determine and associate patterns in any zero padded binary data. This also allows for the simulation of [full-batch](https://visualstudiomagazine.com/articles/2014/08/01/batch-training.aspx) training. The option to export the trained synaptic weights is also available. This allows you to train the network on a certain set of data, export the synapses, and then later import them to run the network in validation mode.
19 |
20 | Thanks to OpenGL, ( more specifically the OpenGL, OpenGL ES, and Vulkan development library GLFW, and GLEW for function pointer association ) you are able to watch the neural network learn. The fact that the base network is 4 layers is important for this implementation because that means that there are 3 synaptic weight matrices, therefore, allows me to easily map each synapse to a respective Cartesian coordinate axis (X,Y,Z). I then render the location of the normalized ( -1.0 to 1.0 ) synaptic weight values to the screen and redraw each frame without clearing so a path can be seen ( default mode ).
21 |
22 | Three visualization modes are available: Default, Line, Dot, and Tri. ( The picture shown is tri ). These options can be changed via compiling with the respective flag. I have yet to implement rotation so all that can really be seen right now is X and Y.
23 |
24 | The visualization of the synapse deltas during training greatly slows the training loop due to the overhead of OpenGL, but this could probably be minimized with a multi-threaded support.
25 |
26 | For more info on running/compiling and more screen shots, [Check it out on Github!](https://github.com/jmp1617/deepnet)
27 |
28 |
--------------------------------------------------------------------------------
/_includes/head.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ site.title }}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/about/faq.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: page
3 | title: Frequently Asked Questions
4 | active: about-faq
5 | ---
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
Do I need to be a Computer Science major to join?
14 |
Nope, CSH accepts students from any program at RIT!
15 |
16 |
17 |
Do I need to be a 1st year to join?
18 |
19 | Also no! You can join our introductory process at any point of your RIT academic career!
20 | Learn more about applying.
21 |
22 |
23 |
24 |
How do I join?
25 |
26 | Check out our page on New Members to learn more about applying and joining CSH.
27 |
28 |
29 |
30 |
Does being a member cost anything?
31 |
32 | Our active membership dues are $80/semester.
33 | Our operating budget is formed every year from dues paid by members in addition to sponsorships, and helps fund improvements to our floor, member projects, and social events!
34 | Members unable to afford their dues can speak to our Financial Director and have their dues waived or adjusted.
35 |
36 |
37 |
38 |
Is CSH a fraternity?
39 |
40 | No, we're a Special Interest House: a space in RIT's dorms designed for students who share common interests to live together.
41 | Read more here about SIHs here,
42 | and more about RIT Fraternity and Sorority Life here.
43 |
56 |
--------------------------------------------------------------------------------
/assets/js/slider.js:
--------------------------------------------------------------------------------
1 | const SCROLL_ANIMATION_DURATION = 1000;
2 | const CAROUSEL_SCROLL_DOWN_BUTTON_OFFSET = {X: -5, Y: -25};
3 |
4 | $(document).ready(() => {
5 | let slider = $("#slider");
6 | if(slider.length === 0) return;
7 | if (slider.length) {
8 | slider.slick({
9 | dots: true,
10 | autoplay: true,
11 | autoplaySpeed: 5000,
12 | mobileFirst: true,
13 | swipe: true,
14 | });
15 | }
16 | // Setup carousel scroll-down button click event
17 | let carousel_scroll_down_button = $("#carousel-scroll-down-button");
18 | if(carousel_scroll_down_button.length === 0) return;
19 | let scrollTopOffset = 1;
20 | carousel_scroll_down_button.on("click", () => {
21 | let calculateFinalPosition = () => slider.find("img").height() + scrollTopOffset - $("nav").outerHeight();
22 | let animateProperties = { scrollTop: calculateFinalPosition() }
23 | $("html, body").animate(animateProperties, {duration: SCROLL_ANIMATION_DURATION, specialEasing: {scrollTop: "easeOutCubic"}, step: function(now, fx) {fx.end = calculateFinalPosition();}} );
24 | carousel_scroll_down_button.blur();
25 | });
26 |
27 | // Carousel arrow positioning function
28 | let recalculate_arrow_position = () => {
29 | let sliderBottom = slider.height() + slider.offset().top;
30 | let windowBottom = $(window).scrollTop() + $(window).height();
31 | if ($(window).scrollTop() > sliderBottom) {
32 | carousel_scroll_down_button.css("visibility", "hidden");
33 | } else {
34 | if(windowBottom < sliderBottom){
35 | carousel_scroll_down_button.css("transform", `translate3d(${-carousel_scroll_down_button.width()/2 + CAROUSEL_SCROLL_DOWN_BUTTON_OFFSET.X}px, ${windowBottom-carousel_scroll_down_button.height() + CAROUSEL_SCROLL_DOWN_BUTTON_OFFSET.Y}px,0px)`);
36 | } else{
37 | carousel_scroll_down_button.css("transform", `translate3d(${-carousel_scroll_down_button.width()/2 + CAROUSEL_SCROLL_DOWN_BUTTON_OFFSET.X}px, ${slider.height()-carousel_scroll_down_button.height() + CAROUSEL_SCROLL_DOWN_BUTTON_OFFSET.Y}px, 0px)`);
38 | }
39 | carousel_scroll_down_button.css("visibility", "visible");
40 | }
41 | }
42 |
43 | // Position carousel scroll-down button
44 | $(window).on("scroll load resize focus blur", recalculate_arrow_position);
45 | // Set interval (necessary for ensuring positioning when resize events don't trigger properly)
46 | $(window).on("resize", () => {
47 | const maxLoops = 10;
48 | let loops = 0;
49 | let tempInterval = setInterval(() => {
50 | if(loops >= maxLoops) clearInterval(tempInterval);
51 | recalculate_arrow_position();
52 | loops++;
53 | }, 100);
54 | });
55 | recalculate_arrow_position();
56 | });
57 |
--------------------------------------------------------------------------------
/_posts/2018-04-18-capsule-killer.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: Capsule Killer
4 | date: 2018-04-18
5 | categories:
6 | - projects
7 | description: A first-person shooter developed using Unity and C#.
8 | image: /projects/capsuleKiller.png
9 | image-sm: /projects/capsuleKiller.png
10 | author: Zack Yenchik
11 | author-image: https://avatars0.githubusercontent.com/u/34044719?s=460&v=4
12 | author-bio: First Year Computer Science Student at Rochester Institute of Technology
13 | author-email: zyenchik@gmail.com
14 | author-social:
15 | github: https://github.com/zackyenchik
16 | ---
17 | # Summary
18 | [Capsule Killer](https://github.com/zcy3071/CapsuleKiller) is a first-person shooter that I developed to learn more about the skills and
19 | processes involved with game development. Upon launching the game, the player will be met with a main menu that allows them to start a game,
20 | view the controls, or exit the game. When a player starts a game, they will spawn in the center of the map and enemies will begin spawning
21 | at random locations throughout the map every 2-5 seconds. The enemies move towards the player, doing damage upon collision with the player.
22 | The player has the ability to run away from and shoot enemies. The goal of the game is to defeat as many enemies as possible.
23 |
24 | ## The Enemies
25 | The enemies in the game are pretty simple. Once they spawn, they find the player in the game and begin moving towards them.
26 | If the enemy is able to collide with the player they stop moving to avoid pushing the player aroundand then begin doing damage
27 | to the player. Damage is continually dealt until the enemy and player are no longer colliding. It takes 4 shots to destroy an
28 | enemy in the current build of the game.
29 |
30 | ## The Player
31 | Much like the enemies, the player isn't too complex. Input is recorded from the mouse and the W, A, S, and D keys on the keyboard
32 | and translated into movement of the player using some fun vector math. The player also has the ability to press the Space key
33 | to jump. Jumping was actually one of the most difficult aspects of the game for me to figure out. I wanted it to feel smooth, responsive,
34 | and reasonable; I didn't want the player to be able to jump super high. Shooting uses simple raycasting and input detection. If the left
35 | mouse button is clicked, a ray is casted forwad from the player camera's position. If it hits an enemy, the enemy loses 25 health points.
36 |
37 | ## Conclusion
38 | Overall, I had a blast with this project. Developing Capsule Killer was my first true experience working on a large project.
39 | Before this I had never used Git, Unity, or C#, so I had my fair share of issues along the way. These issues, however, were
40 | valuable opportunities to further my understanding of what I was doing. Although the game itself is pretty simple, I think
41 | the experience I gained made it worthwhile, as it has furthered my understanding of things like version control, game engines,
42 | and programming in general.
43 |
44 | Feel free to check out the source code for Capsule Killer [here](https://github.com/zcy3071/CapsuleKiller)!
--------------------------------------------------------------------------------
/about/index.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: page
3 | title: About CSH
4 | active: about
5 | ---
6 |
7 |
8 |
9 |
10 |
11 |
12 | Founded in 1976, Computer Science House is one of the oldest and most active Special Interest Houses of the Rochester Institute of Technology in Rochester, NY. Located on the third floor of the Fredericka Douglass Sprague Perry Hall dormitory, CSH provides a revolutionary living environment for over fifty on-floor and many more off-floor students.
13 |
14 |
15 | In addition to RIT's standard residence hall facilities, CSH has several special multi-purpose rooms, filled with technical and material resources for members to use. CSH's computing resources include student maintained e-mail, newsgroups, database, web space services, a private wired network, and plenty of servers and workstations. Hands-on learning is emphasized to help members get an advantage in their professional and academic careers.
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | CSH is an exciting place to live and learn. There are always fun things to do, interesting projects to work on, and members who are eager to share their expertise in a wide variety of subjects. Members share a feeling of kinship, belonging, and commitment to each other and the organization. The floor has a unique social and academic atmosphere: people here like to learn.
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | CSH organizes annual events such as Tour de Rochester, Welcome Back, Fall Camping, and Holiday Dinner. Other events such as educational seminars, study jams, hackathons, movie nights, Capture the Disk, road trips and bowling nights also occur frequently. Members play intramural sports such as volleyball, dodge ball, soccer, and broomball together.
36 |
37 |
38 | While much has changed over the years, CSH's mission to help its members grow intellectually, socially, and professionally continues to succeed and surpass expectations.
39 |
45 |
--------------------------------------------------------------------------------
/_sass/_triple_image.scss:
--------------------------------------------------------------------------------
1 | $card-size: 300px;
2 | $p-m-default: 20px;
3 |
4 | $black: #111;
5 | $white: #FFF;
6 |
7 | $csh-pink: #b0197e;
8 | $csh-blue: #404b69;
9 | $gray: #f4f4f6;
10 |
11 | // Easing Properties
12 | $easeOutQuad: cubic-bezier(0.250, 0.460, 0.450, 0.940);
13 |
14 | // PX to EM
15 | $browser-context: 16;
16 |
17 | @function em($pixels, $context: $browser-context) {
18 | @if (unitless($pixels)) {
19 | $pixels: $pixels * 1px;
20 | }
21 |
22 | @if (unitless($context)) {
23 | $context: $context * 1px;
24 | }
25 |
26 | @return $pixels / $context * 1em;
27 | }
28 |
29 | // Transition Mixin
30 | @mixin transition($transition...) {
31 | -moz-transition: $transition;
32 | -o-transition: $transition;
33 | -webkit-transition: $transition;
34 | transition: $transition;
35 | }
36 |
37 |
38 | .triple_a {
39 | @include transition(all 300ms $easeOutQuad);
40 | &:hover {
41 | @include transition(all 300ms $easeOutQuad);
42 | }
43 | }
44 |
45 | #wrapper {
46 | position: relative;
47 | display: flex;
48 | height: 100vh;
49 | align-items: center;
50 | justify-content: center;
51 | }
52 |
53 | article.card {
54 | background-image: linear-gradient(0deg, $csh-blue 0%, $csh-pink 100%);
55 | width: $card-size;
56 | height: $card-size;
57 | margin: $p-m-default;
58 | position: relative;
59 | overflow: hidden;
60 | }
61 |
62 | .card-image {
63 | max-width: 100%;
64 | width: 100%;
65 | height: $card-size;
66 | object-fit: cover;
67 | transform: translate(0,0);
68 | @include transition(all 400ms $easeOutQuad);
69 | }
70 |
71 | .card-meta {
72 | font-size: em(11);
73 | text-transform: uppercase;
74 | letter-spacing: 1px;
75 | &:before {
76 | content: '';
77 | height: 1px;
78 | width: 30px;
79 | background-color: #fff;
80 | position: relative;
81 | display: block;
82 | margin-bottom: 10px;
83 | backface-visibility: hidden;
84 | opacity: 0;
85 | transform: translate(0,-10px);
86 | @include transition(all 200ms $easeOutQuad);
87 | }
88 | }
89 |
90 | .card-text {
91 | color: #FFF;
92 | // This next line controls the background opacity
93 | background-color: rgba($black, .40);
94 | position: absolute;
95 | padding: $p-m-default;
96 | z-index: 10;
97 | width:100%;
98 | height: 100%;
99 | display: flex;
100 | flex-wrap: wrap;
101 | align-content: flex-end;
102 | @include transition(all 200ms $easeOutQuad);
103 | }
104 |
105 | .card-title {
106 | margin: 8px 0;
107 | font-weight: 300;
108 | font-size: em(30);
109 | }
110 |
111 | @media screen and (min-width: 800px) {
112 | .card a {
113 | &:hover {
114 | .card-text {
115 | background-color: rgba($black, .60);
116 | }
117 | .card-meta {
118 | &:before {
119 | transform: translate(0,0);
120 | opacity: 1;
121 | @include transition(all 200ms $easeOutQuad);
122 | }
123 | }
124 |
125 | .card-image {
126 | transform: translate(20px,0);
127 | @include transition(all 400ms $easeOutQuad);
128 | }
129 | }
130 | }
131 | }
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/_includes/nav.html:
--------------------------------------------------------------------------------
1 |
36 |
--------------------------------------------------------------------------------
/_posts/2018-04-11-kudos-mapping-and-slam.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: Kudos Mapping and SLAM Project
4 | date: 2018-04-11
5 | categories:
6 | - Robotics
7 | - SLAM
8 | - ROS
9 | - Mapping
10 | - Project
11 | description: Added LiDAR mapping functionality to Computer Science House's floor robot, Kudos.
12 | image: /projects/CSH_Map_2.png
13 | image-sm: /projects/CSH_Map_2.png
14 | author: Trevor Sherrard
15 | author-image: http://www.trevorsherrard.com/images/profile_pics.jpg
16 | author-bio: Electrical Engineer, roboticist, computer vision enthusiast. I have a strong passion for seeing my software come alive in my projects.
17 | author-email: tws4129@rit.edu
18 | author-social:
19 | github: https://github.com/sherrardTr4129
20 | linkedin: https://www.linkedin.com/in/trevor-sherrard
21 | ---
22 |
23 | ## Background
24 | Computer Science House purchased a robot chasis from one of our members in the Spring semester of 2017. I had worked on previous versions of the CSH H.E.R.O.I.N project and thought I would be able to make significant strides given we now had a stable robot chassis. So, using robot operating system constructs and several new pieces of hardware/sensors, I added mapping functionality to Kudos.
25 |
26 | ## Details
27 | First, I needed to install a LiDAR sensor on the robot. Standard off-the-shelf LiDAR solutions, such as the 16-channel Velodyne puck, start at upwards of $5000. Being a student organization, we needed a more financially sensible solution. I decided on using a replacement LiDAR sensor from the NeatoXV robot vacuum cleaner. Once the serial communication between the LiDAR controller board was setup with the Raspberry Pi, ROS development began. The LiDAR scans were "off-boarded" from the robot via the rostopic /laserscan over the network to a VM running on CSH Proxmox. On this VM, a program subscribed to this data and performed an algorithm to simultaneously localize the robot within a map and build the map as the robot moved through its enviornment. A navigation goal could be set for the robot to navigate to, and a path to follow to obtain this goal was computed. From this path, individual robot movements were calculated and streamed to the robot via Computer Science House's WiFi network. This robot movement was actuated upon by the robot through its move base controller. See the figure below for a drawing of the control topology for Kudos.
28 |
29 | 
30 |
31 | ## Future Iterations
32 | For anyone thinking about working on this project in future student generations, make sure to develop/use a SLAM algorithm that takes its odometry data from encoders. Currently the software setup relies on a fairly consistent LiDAR scan update rate and a large difference between LiDAR scan frames. Unfortunately, most walls are very flat and not very feature-rich. Even more unfortunate, most of CSH is comprised of very flat walls, so Kudos had some difficulty navigating when traveling through long, straight hallways. Kudos has gearboxes that allow for easy install of AndyMark standard encoders.
33 |
34 | ## GitHub Links
35 | Have a look at the project setup and code below!
36 |
37 | [Kudos ROS package](https://github.com/ComputerScienceHouse/Kudos/tree/master/kudos_csh)
38 |
39 | [MoveBase Controller](https://github.com/ComputerScienceHouse/Kudos/tree/master/KudosROS)
40 |
--------------------------------------------------------------------------------
/_posts/2018-04-12-proxstar.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: Proxstar
4 | date: 2018-04-12
5 | categories: projects
6 | description: Proxstar is a VM self-service tool that integrates with Proxmox and STARRS
7 | image: /projects/proxstar.png
8 | image-sm: /projects/proxstar.png
9 | author: Jordan Rodgers
10 | author-image: https://avatars1.githubusercontent.com/u/5183608?s=460&v=4
11 | author-bio: Fourth Year Networking & Systems Administration Student at Rochester Institute of Technology
12 | author-email: com6056@csh.rit.edu
13 | author-social:
14 | github: https://github.com/com6056
15 | ---
16 |
17 | ## The Problem
18 | CSH currently uses Proxmox for VM hosting. It has been working great for every use case we have for it with one exception: member VM self-service. The interface isn't very intuitive to someone who might not have created a VM before, creating a higher barrier to entry than we would like for members who might want to start learning how to use Linux for the first time. It also lacked the ability to enforce resource limits and automatically cleanup VMs that members weren't using anymore. All of my previous major projects were much more operations and/or security focused so I figured writing something to solve this problem would be a great way to do a much more development focused project and expand my developer skillset.
19 |
20 | ## The Solution
21 | Proxstar (a mashup of Proxmox, a VM hosting solution, and STARRS, an IP/DNS/DHCP management system) is a web application that allows for easy VM self-service for the members of CSH. It is written in Python using Flask and runs on the CSH OpenShift cluster. RQ is being used as a task queue for tasks that take more than a second or two and periodic tasks (RQ-Scheduler). Proxstar allowed members to create, edit, and delete VMs and will automatically handle any network registration that needs to be done in STARRS for them. During creation, they can specify to either create it from a template or to install it themselves from an ISO. If creating it from a template, Proxstar will spin up a ready-to-go VM with a a user that has a randomly generated password for the member to use.
22 |
23 | #### Making RTPs' Lives Easier
24 | Having to periodically go through and clean up VMs that haven't been touched by members in months can be a tedious task. Enforcing usage limits can also be difficult since Proxmox doesn't have a mechanism for doing so. Proxstar allows RTPs to set a limit on the number of CPU cores and amount of memory and disk space a member can utilize. It also sets an expiration date on each new VM, emails the member before it expires, and automatically deletes any VMs that aren't renewed.
25 |
26 | #### Struggles
27 | The hardest part of the project was figuring out how to give console access to members. Proxmox does not provide a friendly way to access their VNC consoles, so I had to dig into it to figure out how they did it and try to do a similar thing within Proxstar. Upon clicking the 'Console' button, Proxstar generates a valid token for the port that the noVNC session will be spun up on. It then forwards the port that the actual VNC session will be spun up on from the respective Proxmox host to the noVNC instance within Proxstar and starts the VNC session for the VM on Proxmox. Finally, Proxstar opens a new tab with the noVNC session and a valid token to access it. It isn't the cleanest solution, but it has held up pretty well.
28 |
29 | ##### Feel free to check out the source code for Proxstar [here](https://github.com/com6056/proxstar)!
30 |
--------------------------------------------------------------------------------
/assets/css/main.scss:
--------------------------------------------------------------------------------
1 | ---
2 | # this ensures Jekyll reads the file to be transformed into CSS later
3 | # only Main files contain this front matter, not partials.
4 | ---
5 |
6 | $CSHPUBSITE_ASSETS_URL: "{{site.env.CSHPUBSITE_ASSETS_URL}}";
7 | $blue: #404b69;
8 | $gray: #f4f4f6;
9 | $csh-pink: #b0197e;
10 |
11 | body {
12 | position: relative;
13 | width: 100%;
14 | height: 100%;
15 | padding: 0;
16 | margin: 0;
17 | overflow: overlay; // For transparent scrollbar
18 | background: white;
19 | }
20 |
21 | /* Scrollbar (only supported by some browsers) */
22 | ::-webkit-scrollbar {
23 | width: 12px;
24 | }
25 |
26 | ::-webkit-scrollbar-track {
27 | background: transparent;
28 | }
29 |
30 | ::-webkit-scrollbar-thumb {
31 | box-shadow: inset 0px 0px 10px 10px rgba(0,0,0,0.2);
32 | border: 3px solid transparent;
33 | border-radius: 5px;
34 | }
35 |
36 | ::-webkit-scrollbar-thumb:hover {
37 | box-shadow: inset 0px 0px 10px 10px rgba(0, 0, 0, 0.4);
38 | border: 2px solid transparent;
39 | }
40 |
41 | .container.spaced {
42 | padding-top: 50px;
43 | padding-bottom: 50px;
44 | }
45 |
46 | .gray-wrapper {
47 | padding-top: 10px;
48 | padding-bottom: 10px;
49 | background: $gray;
50 | &.padded {
51 | padding-top: 30px;
52 | padding-bottom: 30px;
53 | }
54 | }
55 |
56 | img.rounded,
57 | .card {
58 | width: 100%;
59 | border-radius: 8px;
60 | box-shadow: 0 2px 15px darken($gray, 20%);
61 | }
62 |
63 | .container {
64 | display: flex;
65 | flex-direction: row;
66 | flex-wrap: wrap;
67 | justify-content: space-evenly;
68 | align-items: flex-start;
69 | }
70 |
71 | .container_stat {
72 | display: flex;
73 | flex-direction: row;
74 | flex-wrap: wrap;
75 | justify-content: space-evenly;
76 | align-items: flex-start;
77 | }
78 |
79 | .stat_big {
80 | color: $csh-pink;
81 | font-size: 2.5em;
82 | font-weight: 600;
83 | margin: 0%;
84 | }
85 |
86 | .stat_tag {
87 | margin: 0.2em;
88 | }
89 |
90 | .stat_card {
91 | text-align: center;
92 | width: 200px;
93 | }
94 |
95 | .stat_desc {
96 | font-size: 0.6em;
97 | font-weight: 600;
98 | }
99 |
100 | .card-header {
101 | overflow: hidden;
102 | text-overflow: ellipsis;
103 | }
104 |
105 | img.center-vertically {
106 | width: 80%;
107 | height: auto;
108 | position: relative;
109 | top: 50%;
110 | transform: translateY(-50%);
111 | }
112 |
113 | img.padded-gray {
114 | padding: 10%;
115 | background: #EEEEEE;
116 | }
117 |
118 | .logo-grid {
119 | & img {
120 | width: 100%;
121 | margin-top: 1.5em;
122 | transition: 0.3s opacity;
123 | &:hover {
124 | opacity: 0.75;
125 | }
126 | @media (max-width: 992px) {
127 | margin-top: 1em;
128 | }
129 | }
130 | }
131 |
132 | a.btn {
133 | font-size: 0.75em;
134 | margin-bottom: 1em;
135 | }
136 |
137 | @media screen and (max-width: 570px) {
138 | .quad_image {
139 | display: block;
140 | }
141 | }
142 |
143 | @media screen and (min-width: 571px) {
144 | .quad_image {
145 | display:grid;
146 | grid-template-columns: 50% 50%;
147 | }
148 | }
149 |
150 | @media screen and (min-width: 1100px) {
151 | .quad_image {
152 | display:grid;
153 | grid-template-columns: 25% 25% 25% 25%;
154 | }
155 | }
156 |
157 |
158 |
159 | @import "typography";
160 | @import "nav";
161 | @import "slider";
162 | @import "about";
163 | @import "projects";
164 | @import "sponsors";
165 | @import "splash";
166 | @import "post";
167 | @import "eboard";
168 | @import "tour";
169 | @import "insights";
170 | @import "footer";
171 | @import "hackathon";
172 | @import "triple_image";
173 | @import "project_images.scss";
174 |
--------------------------------------------------------------------------------
/_posts/2018-03-28-creating-go-in-swift.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: Creating Go in Swift
4 | date: 2018-03-28
5 | categories:
6 | - projects
7 | description: A functional version of Go in Swift, using SpriteKit
8 | author: Zachary Williams
9 | image: /projects/nikhedonia.png
10 | image-sm: /projects/nikhedonia.png
11 | author-image: https://avatars0.githubusercontent.com/u/5004737?s=460&v=4
12 | author-bio: Undergraduate student studying computer science at the Rochester Institute of Technology. I specialize in web & app development, as well as user experience design.
13 | author-email: zachwilliams.me@gmail.com
14 | author-social:
15 | github: https://github.com/ZachTheSloth
16 | linkedin: https://www.linkedin.com/in/z-n-w/
17 | ---
18 |
19 | This project is an implementation of the board game 'Go' for iOS using Swift and and the SpriteKit framework. Go is a board game focused on surrounding enemy tiles to capture territory and remove the tiles from play. To accomplish this, I had to develop an algorithm to efficiently detect if a tile (or group of tiles) was fully surrounded, as well as practice the MVC structure for cleaner code. Using SpriteKit allowed me to take advantage of the sprite system to make logical 'tile' objects, as well as buttons and informational labels that could be animated.
20 |
21 | The algorithm behind the checking of surrounded tiles works by iterating though all the tiles on the board. For each tile, if any of the tiles directly next to it (up, down, left, or right) are blank, it is considered able to "breath," so it is not removed. If there are no blank tiles, it checks if any tiles of the same color next to it are also able to "breath" (since in Go, tiles connected to other tiles of the same color can "breath" through each other). If none of these conditions are met, the tile must be surrounded, so it gets removed.
22 |
23 | When working on this algorithm I ran into two major issues. The first issue had to do with the fact that when I determined a tile to be surrounded, I would remove it instantly. This would cause problems when checking the rest of the tiles on the board, because they would then consider the previously-removed tile as blank. To solve this, I would add each surrounded tile to an array, then iterate through it so they would effectively all be removed at once.
24 |
25 | The second major issue had to do with a special rule in Go. The rule states that even if a spot on the board is already surrounded, you can still place a piece there if it would result in the surrounding tiles to be removed. My algorithm initially did not account for that, so I had to adjust it. I solved this issue by first removing any surrounded tiles regardless of their effect, and then placing them down a second time before running the algorithm again. This meant that if a tile had no effect, it would get placed and removed twice — easy. If placing it down would result in other tiles being removed, however, it would remove them on the first pass and then successfully place the tile down during the second pass.
26 |
27 | SpriteKit was also a large part of the project. I intended to use SpriteKit in this project both to learn how to use it and to make the game feel more responsive with the use of animations. I had never used SpriteKit before this game, and a chunk of the time spent on the project was dedicated to learning how to use it correctly. SpriteKit made it easy to create the exact animations I wanted for all the UI elements, without a major performance hit.
28 |
29 | Overall, the project was a great learning experience, both improving my general development skills and giving me more experience with iOS programming. In the future I plan to expand the game further, and build a strategy game based on Go.
30 |
31 | To see the code, [check out the GitHub project]
32 | (https://github.com/ZachTheSloth/NIKHEDONIA).
33 |
--------------------------------------------------------------------------------
/assets/js/sponsors.js:
--------------------------------------------------------------------------------
1 | ---
2 | ---
3 |
4 | import {pathJoin} from "./utility.js";
5 |
6 | class Sponsor { // this may be extra, ¯\_(ツ)_/¯
7 | constructor(image, url, name) {
8 | this.image = pathJoin("{{ site.env.CSHPUBSITE_ASSETS_URL }}", image);
9 | this.url = url;
10 | this.name = name;
11 | }
12 | }
13 |
14 | $(document).ready(() => {
15 | if ($('#homepage-sponsors').length) {
16 | const sponsors = [
17 | new Sponsor('/sponsors/ritLarge.png', 'http://rit.edu', 'Rochester Institute of Technology'),
18 | new Sponsor('/sponsors/symantec.png', 'http://symantec.com', 'Symantec'),
19 | new Sponsor('/sponsors/att.png', 'http://att.com', 'AT&T'),
20 | new Sponsor('/sponsors/datto.png', 'http://datto.com', 'Datto'),
21 | new Sponsor('/sponsors/UofR.png', 'http://rochester.edu', 'University of Rochester'),
22 | new Sponsor('/sponsors/linkedin.png', 'http://linkedin.com', 'LinkedIn'),
23 | new Sponsor('/sponsors/microsoft.png', 'http://microsoft.com', 'Microsoft'),
24 | new Sponsor('/sponsors/cisco.png', 'http://cicso.com', 'Cisco'),
25 | new Sponsor('/sponsors/google.png', 'http://google.com', 'Google'),
26 | new Sponsor('/sponsors/hp.png', 'http://hp.com', 'HP'),
27 | new Sponsor('/sponsors/johnsonjohnson.png', 'http://jnj.com', 'Johnson and Johnson'),
28 | new Sponsor('/sponsors/lourdesindustries.png', 'http://lourdesinc.com', 'Lourdres Industries'),
29 | new Sponsor('/sponsors/mooreresearchcenter.png', 'http://mrci.com', 'Moore Research Center'),
30 | new Sponsor('/sponsors/intergraph.png', 'http://intergraph.com', 'Intergraph'),
31 | new Sponsor('/sponsors/janestreet.png', 'http://janestreet.com', 'Jane Street'),
32 | new Sponsor('/sponsors/northropgrumman.png', 'http://northropgrumman.com', 'Northrop Grumman'),
33 | new Sponsor('/sponsors/sonus.png', 'http://sonus.net', 'Sonus'),
34 | new Sponsor('/sponsors/oracle.png', 'http://oracle.com', 'Oracle'),
35 | new Sponsor('/sponsors/perforce.png', 'http://perforce.com', 'Perforce'),
36 | new Sponsor('/sponsors/cadence.png', 'http://cadence.com', 'Cadence'),
37 | new Sponsor('/sponsors/podi.png', 'http://podi.com', 'Potomac Digitek'),
38 | new Sponsor('/sponsors/dupont.png', 'http://dupont.com', 'DuPont'),
39 | new Sponsor('/sponsors/amdex.png', 'http://amdexcorp.com', 'Amdex'),
40 | new Sponsor('/sponsors/ti.png', 'http://ti.com', 'Texas Instruments'),
41 | new Sponsor('/sponsors/xerox.png', 'http://xerox.com', 'Xerox'),
42 | new Sponsor('/sponsors/citrix.png', 'http://citrix.com', 'Citrix'),
43 | new Sponsor('/sponsors/fxcm.png', 'http://fxcm.com', 'FXCM'),
44 | new Sponsor('/sponsors/pdhi.png', 'http://pdhi.com', 'PDHI'),
45 | new Sponsor('/sponsors/datadog.png', 'http://www.datadoghq.com/', 'Datadog'),
46 | new Sponsor('/sponsors/dmarcian.svg', 'http://dmarcian.com/', 'dmarcian'),
47 | new Sponsor('/sponsors/pritunl.png', 'https://pritunl.com/', 'Pritunl'),
48 | new Sponsor('/sponsors/sentry.svg', 'https://sentry.io/', 'Sentry'),
49 | new Sponsor('/sponsors/slack.png', 'https://slack.com/', 'Slack'),
50 | new Sponsor('/sponsors/proxmox.png', 'https://proxmox.com/', 'Proxmox'),
51 | new Sponsor('/sponsors/tenable.png', 'https://tenable.com/', 'Tenable'),
52 | new Sponsor('/sponsors/wayfair.png', 'https://wayfair.com/', 'Wayfair'),
53 | new Sponsor('/sponsors/johonnot.png', 'https://johonnottechnologies.com/', 'Johonnot'),
54 |
55 | ];
56 |
57 | for (let i = 0; i <= 6; i++) {
58 | var index = Math.floor(Math.random() * sponsors.length)
59 | var item = sponsors[index];
60 | $('#sponsor-' + i + ' img').attr('src', item.image);
61 | $('#sponsor-' + i + ' a').attr('href', item.url);
62 | $('#sponsor-' + i + ' img').attr('alt', item.name);
63 | sponsors.splice(index, 1);
64 | }
65 | }
66 | });
67 |
--------------------------------------------------------------------------------
/_posts/2018-02-28-swiftfall.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: Swiftfall
4 | date: 2018-02-28 21:25:00
5 | categories: projects
6 | description: A wrapper for an API called Scryfall.
7 | author: Braden Bowdish
8 | image: /projects/swiftfall_screenshot.png
9 | image-sm: /projects/swiftfall_screenshot.png
10 | author-image: https://avatars2.githubusercontent.com/u/15185628?s=460&v=4
11 | author-bio: Lover of Swift and Magic. 3rd year member of Computer Science House.
12 | author-email: bmbowdish@csh.rit.edu
13 | author-social:
14 | github: https://github.com/bmbowdish
15 | ---
16 |
17 | # What is Swiftfall?
18 |
19 | Swiftfall is an API wrapper written in Swift for the API Scryfall.
20 |
21 | [Scryfall](https://scryfall.com/docs/api) is an API which handles information about the card game Magic: The Gathering.
22 |
23 | I like Magic the Gathering, but getting tons of information about Magic cards is really annoying, especially if you don't want to or don't know how to implement a JSON parser or make requests to a website. Many newer developers would like to combine their passions but it's not always easy.
24 |
25 | Thankfully, [Scrython](https://github.com/nandascott/Scrython) does this already, but in Python.
26 |
27 | ### Why Swift Was Appealing
28 | 1. Swift's use of optionals was really appealing. Sometimes you can't be absolutely sure about whether or not a request has been successful. Optionals allow a developer to handle those situations extremely safely.
29 | 2. Swift has a JSON decoder built in and it is appealing to have no dependencies.
30 | 3. iOS, Apple TV, Apple Watch, and MacOS development are all far easier in Swift
31 | 4. Swift is new, and it is fun to do things never done before
32 |
33 | # How do you use Swiftfall?
34 | First, create an executable package. The executable includes a Hello World function by default.
35 |
36 | ```
37 | $ mkdir MyExecutable
38 | $ cd MyExecutable
39 | $ swift package init --type executable
40 | $ swift build
41 | $ swift run
42 | Hello, World!
43 | ```
44 |
45 | Next,
46 |
47 | ```
48 | $ swift package generate-xcodeproj
49 | ```
50 |
51 | This creates the correct package files so you can add dependencies.
52 |
53 | Then, add Swiftfall as a dependency for the executable.
54 |
55 | ```
56 | import PackageDescription
57 |
58 | let package = Package(
59 | name: "MyExecutable",
60 | dependencies: [
61 | // Dependencies declare other packages that this package depends on.
62 | // .package(url: /* package url */, from: "1.0.0"),
63 | .package(url:"https://github.com/bmbowdish/Swiftfall.git", from: "1.2.0")
64 | ],
65 | targets: [
66 | // Targets are the basic building blocks of a package. A target can define a module or a test suite.
67 | // Targets can depend on other targets in this package, and on products in packages which this package depends on.
68 | .target(
69 | name: "MyExecutable",
70 | dependencies: ["Swiftfall"]),
71 | ]
72 | )
73 | ```
74 |
75 | Then, run:
76 |
77 | ```
78 | $ swift package generate-xcodeproj
79 | ```
80 |
81 | I believe this is because you need to pull down the new dependencies from the source.
82 |
83 |
84 | Now you're ready to use Swiftfall!
85 |
86 | # Actually Using Swiftfall
87 |
88 | ## Getting a Card
89 | `Swiftfall.getCard(fuzzy:String) -> Card? _(Fuzzy search)_`
90 |
91 | `Swiftfall.getCard(exact:String) -> Card? _(Exact search)_`
92 |
93 | `Swiftfall.getRandomCard() -> Card? _(Random Card)_`
94 |
95 | Ex.
96 |
97 | ```
98 | import Swiftfall
99 | let card = Swiftfall.getCard(exact:"Black Lotus")
100 | card?.simplePrint()
101 | ```
102 |
103 | Out.
104 |
105 | ```
106 | Name: Black Lotus
107 | Cost: {0}
108 | Type Line: Artifact
109 | Oracle Text:
110 | {T}, Sacrifice Black Lotus: Add three mana of any one color to your mana pool.
111 | ```
112 |
113 | ## Other Things
114 | Swiftfall supports more than just cards. Other items you can retrieve include:
115 |
116 | * Sets
117 | * Rulings
118 | * Ruling Lists
119 | * Card Lists
120 | * Set Lists
121 |
122 | You can find more information about [Swiftfall on GitHub.com](https://github.com/bmbowdish/Swiftfall)
123 |
--------------------------------------------------------------------------------
/_posts/2022-10-04-slate.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: Slate
4 | date: 2022-10-04
5 | categories:
6 | - projects
7 | description: Event scheduling, simplified.
8 | image: /projects/slate.png
9 | image-sm: /projects/slate.png
10 | author: Andrew Simonson
11 | author-image: https://profiles.csh.rit.edu/image/cinnamon
12 | author-bio: Third year Computer Science major, focusing on data science and predictive analytics.
13 | author-email: asimonson1125@gmail.com
14 | author-social:
15 | github: https://github.com/asimonson1125
16 | linkedin: https://www.linkedin.com/in/simonsonandrew/
17 | website: https://asimonson.com
18 | ---
19 |
20 | This project started with a phone call. I needed to reserve a room for a presentation with some friends and to do that, I had to open the phone app on my phone. I had to converse with a real person, suggesting that, if not Thursday at noon, maybe the following Monday at 4 PM would work.
21 |
22 | Luckily for this scenario, I already knew the schedules of everyone in attendance and I only had to find a time the room was open. But event coordinators greater than myself have always had to juggle the plans of a dozen people, sometimes without actually knowing their schedules, and that's work. Even during the dark ages (read: 2020), that's unacceptable. Let's fix that.
23 |
24 | # Slate
25 | [Slate](https://slate.csh.rit.edu) is an event coordination tool that compiles the calendars of participants to generate a table representing when the most participants can attend. CSH members can link their calendar to their profile, allowing coordinators to load up to date schedules and select event times with maximal attendance.
26 |
27 | # How it works
28 | - Organization members add icalendar (.ics) files from any online calendar service (Google Calendar, Apple Calendar, etc.) to their profile for live calendar updates
29 | - Coordinators select participant members and add additional external calendars and define the searched time period
30 | - Slate uses an LDAP connection to the organization services to download calendars
31 | - date and time intervals are scored with the weighted availabilities of the participants, discarding time intervals where mandatory attendees are unavailable
32 | - Average weekly analysis is generated for planning recurring weekly events
33 |
34 | # Timeline
35 | ## Ver. 1.0 (2020-21)
36 | My freshman year's contribution to Slate was dedicated to creating the calendar compiler and a primitive web interface to interact with the service. Time, as it turns out, is hardly a linear thing in the minds of humans. Even with widely accepted libraries for datetime and icalendar, managing timezone-naive events, daylight savings, and the different calendar services' methodology was by far the greatest challenge Slate faced.
37 |
38 | Working on Slate's web application also introduced me to the Flask framework, Docker, and Openshift. And since all three of these tools became my first choices for all subsequent projects, I'd like to extend my personal thanks to the CSH sysadmin people and RTPs. Thanks to these chads, I'm officially a computer person now.
39 |
40 | ## Ver. 2.0 (2021-22)
41 | Slate should be, by definition, a boring project to work on. Time math is warm and bad. And yet, I couldn't stop working on it. Over the summer, I overhauled the calendar compiler, speeding it up by 12,000% for 3 calendars over a 3 month period. Now it's fast enough to be an actual product to society. I also made the weekly analysis with a much improved UI (websockets! That's new to me) and added the LDAP (also new to me) connection to CSH. CSH members can now add their calendars to their profiles. Guests can still use an open version of Slate without organization profiles.
42 |
43 | # Future
44 | Yeah, I plan.
45 | As of version 2.0 I believe Slate is in a servicable state, but, as with all good ideas, expanding it is totally doable. It might not be much coming from the guy who wrote it, but Slate is more than a gimmick. Slate can easily be made faster, more user friendly, and, Machine Learning Ultimate aside, more helpful in its analysis. I could work on this project until the end of time. If this project taught me anything, it's that these little projects stemming from a mundane phone call can become real products and that it doesn't take a company or even a startup team to make them real. I might be moving on for now, but don't count it out - good projects always have the potential for us to come back to them.
--------------------------------------------------------------------------------
/_posts/2023-02-20-datadog.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: CSH's Use of Datadog in the Server Room
4 | date: 2023-02-20
5 | categories:
6 | - projects
7 | description: "With so many servers in our server room, we need a good way to manage them all. Introducing: Datadog!"
8 | image: /projects/dd.png
9 | image-sm: /projects/dd.png
10 | author: Joe Abbate
11 | author-image: https://profiles.csh.rit.edu/image/skyz
12 | author-bio: Second/Third Year Computing Security BS/MS Major
13 | author-email: joe.abbate@mail.rit.edu
14 | author-social:
15 | github: https://github.com/jabbate19
16 | linkedin: https://www.linkedin.com/in/jabbate19/
17 | website: https://joeabbate.me
18 | ---
19 |
20 | As a student organization, we try to provide our members with tools and experience that will apply to the real world. When it comes to our server room, we wanted a mainstream location to monitor all of our nodes, containers, and virtual machines that keep us going. With the generous donation of [Datadog](https://www.datadoghq.com/) software, we are able to do this using industry-level tools.
21 |
22 | ## What is Datadog?
23 | Datadog provides system and security monitoring to multiple machines, display them in a unified format, and provide alerts for system administrators to see. An Agent is installed on all machines, and these agents communicate to the Datadog servers with data. This data can be compiled into dashboards that provide network-wide statistics, or be used to alert us via Slack.
24 |
25 | ## How do we use it?
26 |
27 | ### Machine Management
28 | All agents on phyisical or virtual machines are installed on our machines via Puppet, which is our preferred method of system management. Once the agent is installed, we receive data on that machine's usage, uptime, and potential security issues.
29 | For containers, we run an [OKD](https://www.okd.io/) cluster that has Datadog's implementation installed. This allows the agent to monitor our containers alongside the bare metal machines. This way, if there happens to be a security issue within a container, it can be identified before it can potentially break out or cause issues.
30 |
31 | ### Website Automation/Checks
32 | Alongside getting statistics from machines, we use Datadog to ensure our websites are functional. We run a lot of websites that are both public and private, so being alerted when these run into an issue is a big plus. The two ways we do this are API checks and workflow checks. In API checks, a Datadog agent reaches out to a specific API on a website and ensures it gets an OK response. If not, it will trigger an alert. In a workflow check, an agent will attempt to load a website like a user and go through a common activity to ensure the user experience is also functional.
33 |
34 | ### Dashboard and Slack Notifications
35 | With all of these alerts and statistics, we need a way to gather and display it all. We have about 70 machines and many websites all producing data. To see all of this, we use dashboards that are displayed on our floor in RIT Dorms. When you get off the elevator to our floor, you can quickly see statistics of our infrastructure and identify if there are any current issues to be addressed. An example of our most popular dashboard is above!
36 |
37 | Alongside this, we enjoy getting detailed, immediate alerts if something happens to go down. Since Slack is our form of communication across the organization, we have channels for Slack alerts. These are also able to be divided by severity or node, so we can pay more attention to alerts that may impact our core infrastructure before we handle a website with a bug.
38 |
39 | ## Open Source!
40 | Personally, I love any project that is open source so I can see how it works and find ways to contribute. A lot of Datadog's code is available on [Github](https://github.com/DataDog), so it can be seen by anyone! In the past, I made a contribution to their MongoDB module to update the parameters used in a Puppet config to set up a database monitor for that server.
41 |
42 | ## Future Implementations
43 | We hope to add custom statistics to our Datadog dashboards in the future to get our members more involved and comfortable with the Datadog experience. A recent project in the works in an Arduino that will provide plant moisture levels for our plants across the floor. Once it gets the data, it will send a UDP packet to one of our nodes using DogStatsd. As we continue to expand our infrastructure, I can guarantee Datadog will be there to help us manage it all. We are college students, and we appreciate the help that Datadog gives us!
44 |
--------------------------------------------------------------------------------
/assets/js/tour.js:
--------------------------------------------------------------------------------
1 | ---
2 | ---
3 | const content = {
4 | 'dorm': {
5 | 'title': 'Dorm Room',
6 | 'photos': ['{{site.env.CSHPUBSITE_ASSETS_URL}}/tour/dorm/1'],
7 | 'description': 'Though the walls are the same as regular dorm rooms, our rooms usually look rather different than the standard RIT room layout.',
8 | },
9 | 'user-center': {
10 | 'title': 'User Center',
11 | 'photos': ['{{site.env.CSHPUBSITE_ASSETS_URL}}/tour/usercenter/1', '{{site.env.CSHPUBSITE_ASSETS_URL}}/tour/usercenter/2'],
12 | 'description': 'The User Center is a productive social room. It is often sought out as a place for members to socialize and get work done. It also serves as a meeting place, a project work room, and a technical seminar room.',
13 | },
14 | 'lounge': {
15 | 'title': 'Lounge',
16 | 'photos': ['{{site.env.CSHPUBSITE_ASSETS_URL}}/tour/lounge/1', '{{site.env.CSHPUBSITE_ASSETS_URL}}/tour/lounge/2'],
17 | 'description': 'The Lounge is CSH\'s main social hub. This room is used to host movie nights, social events, technical seminars, company visits, and E-Board meetings.',
18 | },
19 | 'server-room': {
20 | 'title': 'Server Room',
21 | 'photos': ['{{site.env.CSHPUBSITE_ASSETS_URL}}/tour/server/1', '{{site.env.CSHPUBSITE_ASSETS_URL}}/tour/server/2'],
22 | 'description': 'CSH\'s server room serves as a place for members to learn and practice their networking skills. It also serves as a place to host the variety of network services provided to our members.',
23 | },
24 | 'software-room': {
25 | 'title': 'Software Room',
26 | 'photos': ['{{site.env.CSHPUBSITE_ASSETS_URL}}/tour/software/1', '{{site.env.CSHPUBSITE_ASSETS_URL}}/tour/software/2'],
27 | 'description': 'The Software Room is the perfect place for small group tasks. It is a quiet room that is away from the normal hustle and bustle of floor which makes it great for taking phone calls, playing board games, and working on group assignments. The Software Room also houses CSH\'s book collection as well as a variety of board games.',
28 | },
29 | 'research-room': {
30 | 'title': 'Research Room',
31 | 'photos': ['{{site.env.CSHPUBSITE_ASSETS_URL}}/tour/research/1', '{{site.env.CSHPUBSITE_ASSETS_URL}}/tour/research/2', '{{site.env.CSHPUBSITE_ASSETS_URL}}/tour/research/3', '{{site.env.CSHPUBSITE_ASSETS_URL}}/tour/research/4'],
32 | 'description': 'The Research Room is CSH\'s workshop. It houses our two 3D Printers, as well as the tools and materials for members\' electronics projects.',
33 | },
34 | 'library': {
35 | 'title': 'Library',
36 | 'photos': ['{{site.env.CSHPUBSITE_ASSETS_URL}}/tour/library/1', '{{site.env.CSHPUBSITE_ASSETS_URL}}/tour/library/2'],
37 | 'description': 'The Library is CSH\'s multi-function archive and arcade. It serves as a storage place for all of our historical records and keepsakes as well as a variety of arcade machines, both vintage and custom-built.',
38 | },
39 | };
40 |
41 | const constructSliderHTML = (room) => {
42 | let innerHTML = '';
43 | for (let photo of room.photos) {
44 | innerHTML += `
45 |
46 |
47 |
48 |
49 | `;
50 | }
51 | return innerHTML;
52 | };
53 |
54 | $(document).ready(() => {
55 | if ($('#tour-page').length) {
56 | const room = content['dorm'];
57 | $('#slider').slick('unslick');
58 | $('#tour-description').text(room.description);
59 | $('#tour-title').text(room.title);
60 | $('#slider').html(constructSliderHTML(room));
61 | $('#slider').slick({
62 | dots: true,
63 | autoplay: true,
64 | autoplaySpeed: 5000,
65 | mobileFirst: true,
66 | });
67 | $('.dropdown-item').click(function(e) {
68 | e.preventDefault();
69 | $('.dropdown-item.active').first().removeClass('active');
70 | $(this).addClass('active');
71 | $('#slider').slick('unslick');
72 | const room = content[$(this).attr('id')];
73 | $('#tour-description').text(room.description);
74 | $('#tour-title').text(room.title);
75 | $('#slider').html(constructSliderHTML(room));
76 | $('#slider').slick({
77 | dots: true,
78 | autoplay: true,
79 | autoplaySpeed: 5000,
80 | mobileFirst: true,
81 | });
82 | });
83 | }
84 | });
85 |
--------------------------------------------------------------------------------
/_posts/2025-03-26-netbox.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: Upgrading NetBox
4 | date: 2025-03-26
5 | categories:
6 | - projects
7 | description: "With so many servers in our server room, we need a good way to manage them all. Introducing: Datadog!"
8 | image: /projects/netbox.png
9 | image-sm: /projects/netbox.png
10 | author: Cecilia Lau
11 | author-image: https://profiles.csh.rit.edu/image/pixel
12 | author-bio: Computer Science Major
13 | author-email: pixel@csh.rit.edu
14 | author-social:
15 | github: https://github.com/cecilialau6776
16 | linkedin: https://www.linkedin.com/in/lau-cecilia/
17 | ---
18 |
19 | # NetBox
20 | So we had started an update to NetBox, a solution for modelling and documenting networks. Unfortunately, we never finished the update, leaving the application in a broken state for several months. This article describes the troubleshooting done and actual steps taken to get NetBox back up and running. While we plan to move to NetBox for our IP management and resource registration, we have several more steps to take before we fully migrate. At the moment, we use STARRS, an in-house solution for IP management and resource registration. STARRS has served us well thus far, but it's long overdue for us to move to a more complete solution.
21 |
22 | ## What is NetBox? What does it do?
23 | NetBox is a Django application that models and documents networks. We define systems, the interfaces attached to the systems, and assign them IP addresses. It also has the capability to visualize what and where things are in our server racks and even documents cables, helping tremendously for when we have to do maintenance. However, by default, it doesn't have the ability to write entries to our DNS and DHCP servers, which is one of the primary features we need to replace [STARRS](https://github.com/ComputerScienceHouse/starrs-web), our current IPAM and DNS solution. Luckily, NetBox's community has created plugins that allow for this and even for syncing switch and router configuration. Using and configuring these plugins would let use NetBox as a single source of truth, simplifying how we configure our network.
24 |
25 | ## Troubleshooting and Fixing NetBox
26 | What we had was an incompletely upgraded NetBox, and internal server errors with strange errors in the logs. Initially, we thought that we had tried to migrate the database directly from 3.6.X to 4.X, but NetBox requires migrating to the latest minor release of the major version (3.7.X) before updating to the next major version (4.X). If that was the case, the best solution would have been to restore the database from a backup (which we didn't have). Luckily for us, this wasn't the problem, so we moved on.
27 |
28 | We had several plugins (`netbox-topology-views`, `social-auth-app-django`, and `netbox-plugin-dns`) installed and enabled. So, first things first - let's find out if the problem is one of the plugins by disabling them all. And... voila! We are no longer presented with an error page. Our prime suspect was `netbox-topology-views`, since it'd caused problems in the past. And after simply bumping the version to its latest, everything seemed to work fine.
29 |
30 | However, a while ago, we'd commented out a few lines of our OIDC groups handler which would sync NetBox user groups with our groups in LDAP. This means that while the page _was_ running, users wouldn't get their groups synced, so our fix would be mildly incomplete. Since I was the one who wrote that handler, I looked into a bit more. I was getting errors like `Field id expected number but got Group`, but the documentation said that everything should've been fine, since the argument I'm passing into `user.groups.set()` was correct. After a little bit of poking around in the Django shell, I find that my import (`from django.contrib.auth.models import Group`) fails, with an error basically saying that this "Group" model is disabled in favor of something else. Turns out that NetBox had updated their system to use a custom `Group` instead of Django's built-in version. A simple change to the import fixed group syncing.
31 |
32 | The largest issues seemed to be fixed, but a few clicks around would again present internal server errors. The messages we got looked to be the database columns not being quite right, so I went ahead and ran the database migrations, and like magic, all the errors are gone!
33 |
34 | The [actual changes](https://github.com/ComputerScienceHouse/netbox-images/pull/5/files) needed were remarkably simple, but let this be a lesson to take database backups and document what was done if you don't complete a migration.
35 |
36 | For NetBox to actually replace STARRS, we still need to work out the plugins that [do the thing that starrs does] and also work towards having NetBox manage our switch and router configurations. For now though, having a working version at all is a major improvement from three months ago and will allow us to actually take these next steps.
37 |
--------------------------------------------------------------------------------
/_posts/2020-05-19-docker-rust-notpresent.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Debugging Error: NotPresent with Rust in Docker"
3 | description: "A friend's Docker container was exiting with Error: NotPresent and no other information. I embarked on a deep dive for an ultimately simple cause."
4 | layout: post
5 | date: 2020-05-19
6 | image: /projects/carbon.png
7 | image-sm: /projects/carbon.png
8 | author: Galen Guyer
9 | author-image: https://cdn.galenguyer.com/img/avatars/headshot.jpg
10 | author-email: chef@csh.rit.edu
11 | author-social:
12 | github: https://github.com/galenguyer/
13 | categories: [docker, rust]
14 | ---
15 |
16 | Check out this post on Galen's blog!
17 |
18 |
Today, a friend posted the following snippet in Slack:
The first guess was that they had deleted the docker image and forgot to rebuild it. That wasn't the case, leading me to dive into this cryptic error message that we assumed was some hidden Rust or Docker error. We weren't able to find any example of this error message for Rust or Docker online, so I knew this would be a fun challenge.
22 |
23 |
The first thing I did was to make sure the path to the binary was working, as it'd be silly if this wasn't working because /usr/local/bin wasn't in the container's PATH. I changed the last line in the Dockerfile from CMD ["shelflife"] to ENTRYPOINT ["/usr/local/bin/shelflife"]. The error persisted, which meant it wasn't a PATH error. Of course this couldn't be easy.
24 |
25 |
The next step in diagnosis was to get a shell on the container. That would typically be done via docker exec, but that only works on a running container, which we didn't have. To get around this, I changed the last line of the Dockerfile to ENTRYPOINT ["/bin/bash"], which makes docker run -it drop you into an interactive bash shell. This means I could easily see what was going on and run commands from inside the container.
26 |
27 |
Now that I had a shell, I navigated to /usr/local/bin/ and ran ./shelflife to check if there was any output docker was hiding. Unfortunately, there wasn't. I was at roughly the same place as when I started - a cryptic error message and no idea where it was coming from. At least now I was decently sure it wasn't not a docker issue.
28 |
29 |
I'd run into issues with dynamically linked libraries not being installed in the past, so I used ldd (List Dynamic Dependencies) to make sure all the dependencies existed. Everything looked fine, and I double-checked by manually installing the library packages for everything ldd said was linked. Everything was already installed, but the error persisted.
30 |
31 |
The last thing I tried was installing strace, a tool for tracing system calls, and running strace ./shelflife. This gave me a huge output full of system calls, but near the bottom was something that looked familiar, the text "NotPresent". Now I knew I was on the right path! The relevant output that got me to the final answer was the following:
32 |
33 |
getcwd("/usr/local/bin", 512) = 15
34 | statx(0, NULL, AT_STATX_SYNC_AS_STAT, STATX_ALL, NULL) = -1 EFAULT (Bad address)
35 | statx(AT_FDCWD, "/usr/local/bin/.env", AT_STATX_SYNC_AS_STAT, STATX_ALL, 0x7ffc04639b10) = -1 ENOENT (No such file or directory)
36 | statx(AT_FDCWD, "/usr/local/.env", AT_STATX_SYNC_AS_STAT, STATX_ALL, 0x7ffc04639930) = -1 ENOENT (No such file or directory)
37 | statx(AT_FDCWD, "/usr/.env", AT_STATX_SYNC_AS_STAT, STATX_ALL, 0x7ffc04639750) = -1 ENOENT (No such file or directory)
38 | statx(AT_FDCWD, "/.env", AT_STATX_SYNC_AS_STAT, STATX_ALL, 0x7ffc04639570) = -1 ENOENT (No such file or directory)
39 | write(2, "Error: ", 7Error: ) = 7
40 | write(2, "NotPresent", 10NotPresent) = 10
41 | write(2, "\n", 1
42 | ) = 1
43 | sigaltstack({ss_sp=NULL, ss_flags=SS_DISABLE, ss_size=8192}, NULL) = 0
44 | munmap(0x7fb5000f2000, 8192) = 0
45 | exit_group(1) = ?
46 | +++ exited with 1 +++
47 |
48 |
There it is! Right before exiting, there's several checks for a .env file that all fail. This error didn't happen when run locally, because my friend already made a .env file. However, I never created one, and more critically, the Dockerfile never copied their version of the file into the image. Once we created a .env file and added COPY .env . to the Dockerfile, it started as intended! This wasn't an issue with Docker or Rust at all, but a library giving an unhelpful error message. We couldn't find any documentation of this online, so I hope this post might serve to help anyone else who runs into this issue!
49 |
--------------------------------------------------------------------------------
/_posts/2019-08-26-nickm-intro-letter.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: A Letter to Prospective Members
4 | date: 2019-08-26 21:25:00
5 | categories: intro
6 | description: An explanation of CSH's intro process and the motivations behind it.
7 | author: Nick Mosher
8 | image: /projects/envelope.jpg
9 | image-sm: /projects/envelope.jpg
10 | author-image: https://2.gravatar.com/avatar/82615a3c73fe853714af7b51337a4fac?s=400
11 | author-bio: Software Engineering '20 at RIT and R&D Director at CSH
12 | author-email: nicholastmosher@gmail.com
13 | author-social:
14 | github: https://github.com/nicholastmosher
15 | ---
16 |
17 | Hey there!
18 |
19 | If you’ve made it this far, you’re probably thinking about becoming a member.
20 | That’s great! We need curious and motivated people like you. I want to take a
21 | minute and walk you through our intro process so that you know what to expect;
22 | there’s a handful of steps involved and I want you to have a clear idea of
23 | what you’re getting yourself into.
24 |
25 | The majority of the intro process takes place during the first 10 weeks of
26 | school. The first 2 weeks are what we call “packet season”. Packet season is
27 | all about meeting people - we want CSH to be a tight-knit community, so we
28 | believe that every member should meet every other member. A Packet is a list
29 | of the names of all active CSH members, and one is given to every intro member.
30 | Your job as an incoming CSHer is to seek out and meet as many active members
31 | as you can. This isn’t as easy as hide-and-seek. Once you find an upperclassman,
32 | you have to put in an effort to genuinely get to know them! Ask them about what
33 | their interests are, what projects they’ve done, or how their co-op experiences
34 | have gone. Active members will sign your packet if they think you’d make a good
35 | member of CSH, which is usually the case if you show that you’re passionate and
36 | interested in what you do. After packet season is over, we’ll count up all of
37 | the signatures you’ve collected. If you get a passing percentage of signatures,
38 | congratulations! You’ll receive a CSH account and gain access to all of our
39 | house computer services. If not, there’s still hope! The packet is just one
40 | component of your 10-week evaluation.
41 |
42 | We have a handful of other objectives for you during the 10-week intro process.
43 | These requirements are intended to introduce you to our house culture and
44 | traditions, and are things that active members continue to do throughout their
45 | entire membership. One of the first things we ask you to do is attend some of
46 | our directorship meetings. Each of our 7 directors hosts a weekly meeting where
47 | they discuss ongoing projects, upcoming events, or other news that falls in
48 | their domain. Intro members are expected to attend any 10 directorship meetings
49 | during the 10-week evaluation period, preferably at least one a week. Another
50 | cornerstone of CSH culture is the presentation of technical seminars! Technical
51 | seminars early in the year are usually given by upperclassmen and tend to focus
52 | on introducing you to the world of computer science. Common early-year topics
53 | include setting up basic coding tools, intro to Linux operating systems,
54 | version control for code, and more. Upperclassmen volunteer a lot of time to
55 | prepare seminars, so we ask every intro member to attend at least 2 of them
56 | during their 10 weeks. Plus, this is a special-interest house for computer
57 | science, you probably want to attend as many seminars as you can.
58 |
59 | Our last but most important requirement is for you to attend all of our house
60 | meetings. House meetings happen every Sunday at 7:15pm, and are where the
61 | directors summarize house news and events for the past week and upcoming weeks.
62 | This meeting is required because it’s the one time we have a chance to address
63 | all of house together, and is when we make large decisions as a group. Though
64 | we require you to attend every house meeting, we also understand that life
65 | happens. If you can’t make it because you’re sick or out of town, just let
66 | our Evaluations director know and they’ll write a note about your absence.
67 |
68 | At the end of the 10-week intro process, all of the upperclassmen gather
69 | together to vote on intro members. During this meeting, we look at the big
70 | picture of how well you’ve met the requirements and who you are as a person.
71 | Did you attend at least 10 directorship meetings? Did you get a good score on
72 | packet? Are you a curious and engaged member? Are you friendly and
73 | light-hearted? Remember, we want CSH to be a welcoming and inclusive
74 | community, but we’re also looking for the mad scientist in each of you.
75 |
76 | I hope that this has given you a good idea of what to expect when signing up
77 | for CSH. It’s a crazy ride for sure, but it’s totally worth it. If anything,
78 | I hope I’ve talked you _into_ applying. I look forward to meeting you all when
79 | school starts!
80 |
81 | -@nickm
82 |
--------------------------------------------------------------------------------
/membership/index.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: page
3 | title: Membership
4 | active: membership
5 | ---
6 |
7 |
8 |
9 |
10 |
11 |
12 | Computer Science House boasts some of the best minds in almost every computer-related field. As a member, you will be meeting people who can help you with your classes, teach you new tricks, and assist you in making the absolute most of your college experience, as well as making professional connections and friendships that will last you your entire life.
13 |
14 |
15 | You don't need to be majoring in Computer Science, Software Engineering, or even anything related. Maybe you're a business major, or perhaps an art student; all we expect is that you have an interest in computers, a willingness to be active on floor, and a desire to excel in all aspects of your life.
16 |
17 |
18 |
19 |
20 |
21 |
Incoming Students
22 |
23 | Even before college, a great way to meet members and learn about CSH is to take a tour during RIT's open houses.
24 | On those days, members lead personalized tours of floor, highlighting our unique facilities, exemplary projects, and social atmosphere.
25 | For open house dates, visit the RIT admissions web site.
26 | If you are unable to attend an open house, email our Evaluations Director to schedule a time that is best for you.
27 | After being accepted to RIT, look for the Special Interest Housing selection in your RIT housing application to apply to CSH.
28 |
29 |
Current Students
30 |
31 | Students already enrolled at RIT can apply to join CSH at any time. The best way to apply is to visit CSH (on the third floor of Fredericka Douglass Sprague Perry Hall) and pick up an application from our Evaluations Director. All majors and years are accepted and members can live on or off floor.
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
Member Expectations
41 |
42 | CSH has a number of requirements for its members, made to both maintain involvement and ensure growth as members and professionals. CSH expects its members to:
43 |
44 |
45 |
Attend weekly committee and House meetings
46 |
Attend some of our many social events and technical seminars
47 |
Complete a "Major Project" each year to contribute to CSH or enhance one's knowledge
48 |
49 |
50 |
51 | For more information on our introductory process, click here.
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
Member Benefits
61 |
62 | CSH's perks more than make up for all the work that goes into membership. All members, both on-floor and off-floor, get the following benefits:
63 |
64 |
65 |
Access to all of CSH's facilities (i.e. the Project room) and resources (i.e. web hosting and email)
66 |
Ability to request funds for technical projects, social events, and more
67 |
Voting privileges at all committee and House meetings to approve funds, accept new members, and have a say in how CSH is run
68 |
Knowledge and advice from some of the brightest minds in computing and related fields
69 |
Networking, storytelling, and donations from alumni in the industry
70 |
Professional and personal connections that last a lifetime
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/_posts/2018-02-28-smart-window-shades.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: Smart Window Shades
4 | date: 2018-03-01 00:00:00
5 | categories: projects
6 | description: A web service that allows one to control their window shades using a website
7 | author: Ayush Goel
8 | author-image: https://avatars2.githubusercontent.com/u/10407155?s=460&v=4
9 | author-bio: First Year Computer Science Student at Rochester Institute of Technology
10 | author-email: axg4975@rit.edu
11 | author-social:
12 | github: https://github.com/ag-ayush
13 | linkedin: https://www.linkedin.com/in/ayush-goel-589ba215a/
14 | ---
15 | # Summary
16 | Smart shades is a web service that allows one to control their window shades using a website.
17 | The hardware requirement is a Raspberry Pi (connected to the Internet), a stepper motor, housing for the stepper motor (3D printed), a stepper motor driver (I used the Pololu A4988), a 10K ohm resistor, and a domain.
18 | The application uses Python, Flask, OpenShift in the back end, Bootstrap, JavaScript, and Ajax.
19 | In short, there are two Flask apps running, one on [a CSH domain](https://shades.csh.rit.edu) and one on the Pi.
20 | The Flask app on the CSH website has the JavaScript and Ajax to make requests to the Flask app on the Pi, which can then take care of changing the window shades.
21 |
22 | # The Story
23 | I picked up this IOT project from R&D.
24 | Spencer, our current R&D director, had the hardware (stepper motor, housing for stepper motor, and the stepper motor driver) and asked if someone could do the software by ImagineRIT.
25 | I had some ideas for ImagineRIT, but this one seemed more fun than the rest of them.
26 | I went into this knowing how to code, specifically in Python, but not having a great understanding of how to incorporate the hardware with the software, including web application integration.
27 | I started the project by figuring out how to use RPi.GPIO library by making a simple program with LEDs.
28 | Then I started using the stepper motor driver and the stepper motor.
29 | This ended up being a hardware problem, not a software one.
30 | After countless hours I figured out that I can connect an LED to 2 of the 4 pins of the motor and if the LED lights up upon turning the motor then I have found a pair of wires.
31 | From there I had to figure out how stepper motors work in software, which comparatively was not that difficult.
32 |
33 | The next part of this project was controlling the motor from a website.
34 | I started by reading about **Flask** and making a quick Hello world application on the IP on the Pi.
35 | Since Flask uses python, and so does my code for the shades, I was simply able to combine the two.
36 | I learned about **HTML** and **bootstrap** while creating the index page for this application.
37 |
38 | I now needed a domain that people could type in, because remembering an IP address is only possible when you type it in countless times as the developer.
39 | Thankfully, our OpComm director, Steven, helped me out during the OpCommathon by showing me OpenShift.
40 | As soon as I ran it up, it crashed.
41 | Rpi.GPIO imports can only be run on a Raspberry Pi... I eventually decided to make a second Flask app that would simply run on the CSH domain and link to the IP of the Pi.
42 | This, however, was not ideal because every time you changed the height of the shade, the page would reload.
43 | That is neither pretty nor efficient.
44 | To make the matters worse, the link was to an IP address, and a real world application should not be pointing to an IP address.
45 | I asked around, and upon the suggestion of our financial director, Devin, I decided to implement **Ajax**.
46 |
47 | I had never used JavaScript, nor Ajax prior to this, so it was a bit of learning curve.
48 | Obstacle one was making the script work; aside from syntax, it took a while to realize that script needed to be called after the buttons were created.
49 | Then came other obstacles, such as not being able to POST to Pi because it ran on HTTP and the website ran on HTTPS.
50 | Somewhere in there I had to implement CORS or Cross-Origin Resource Sharing, lack of it crashes the program.
51 | With the help of our chairman, Jordan, I was able to get the Flask application on the Pi running on HTTPS, thereby allowing communication between the CSH domain and the Pi.
52 |
53 | I proceeded to add some more functionality to this application after OpCommathon.
54 | This took a couple day's worth of work because I was still learning JavaScript.
55 | Now you can click buttons to set the height as a percentage, change how many steps or pulses the motor requires to make the shade go from completely down to completely up, and move the motor n steps at a time for debugging purposes.
56 | Furthermore, it shows the current shade percentage.
57 | The idea behind showing that information is that if it does not match up with what you have physically in front of you, then you will know that you need to change your values for the program.
58 | The best part is that the page does not reload upon calling a function, the two apps simply talk to each other.
59 |
60 | Altogether, this project was a lot of fun.
61 | I learned quite a bit, both in the software world and hardware world.
62 | ImagineRIT is still weeks from now, and as a result I plan on adding Amazon Alexa Skill to this, or someway of using voice command to perform the same actions.
63 |
64 | P.S. For details on wiring components, please visit the GitHub source of this project [here](https://github.com/ag-ayush/smart-window-shades).
65 |
--------------------------------------------------------------------------------
/membership/traditions.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: page
3 | title: Traditions
4 | active: membership-traditions
5 | ---
6 |
7 |
8 |
9 |
10 |
11 |
12 | CSH isn’t just about working on projects. Our members love to engage
13 | in a variety of social activities. Many of these activities have
14 | persisted through the years to become traditions.
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
Welcome Back
24 |
25 | Welcome Back is a barbecue held at the beginning of each year to
26 | welcome the incoming freshman class. Traditionally, alumni come from
27 | far and wide to visit current floor members. We cook way too much
28 | food, tell stories, and participate in a variety of outdoor
29 | activities.
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
Camping
39 |
40 | Every year, CSH goes out on an adventure to see if we can survive for
41 | a weekend in the wild. Surprisingly, a bunch of computer nerds can
42 | thrive without electricity for a few days.
43 |
44 |
45 |
46 |
64 |
65 |
66 |
67 |
68 |
69 |
Holiday Dinner
70 |
71 | Holiday Dinner is our annual formal dinner that takes place right
72 | before Winter Break. All of CSH gets dressed up and has dinner at a
73 | classy restaurant.
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
Seminars
83 |
84 | Any member can hold a seminar to teach others a bit about a topic of
85 | their choosing. Subjects can range from programming to juggling and
86 | everything in between, and anyone can give one at any time.
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
Intramural Sports
96 |
97 | We participate in most of the intramural sports RIT offers, including
98 | broomball, hockey, soccer, basketball, softball, dodgeball, and volleyball. While
99 | we aren’t always the best team out there, we’re always the
100 | best-looking (with our CSH jerseys) and have the most fans cheering us
101 | on! We’ve even won quite an impressive number of trophies in the past,
102 | which are proudly displayed in our library.
103 |
104 |
105 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/_posts/2018-04-08-game-night.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: Game Night
4 | date: 2018-04-08
5 | categories: projects
6 | description: A Board and Card Games Database
7 | author: Michael Francis
8 | author-image: https://avatars0.githubusercontent.com/u/4574480?s=460&v=4
9 | author-bio: First Year Computer Science Masters Student at Rochester Institute of Technology
10 | author-email: maf1144@rit.edu
11 | image: /projects/game-night.png
12 | image-sm: /projects/game-night.png
13 | author-social:
14 | github: https://github.com/mfrancis95
15 | linkedin: https://www.linkedin.com/in/mfrancis95/
16 | ---
17 |
18 | ## Background
19 |
20 | In the Fall of 2017, I created a Slack channel for Computer Science House called **#game-night** (formerly known as **#card-games**). The purpose of the channel was to help the organization's members get together to play many of the fun board and card games owned by CSH. As of the Spring of 2018, the channel has really been taking off. Seeing that rise in popularity, I decided to do more with this neat corner of CSH and develop a web application that would benefit those who frequented the game nights and the organization as a whole.
21 |
22 | ## Introducing Game Night
23 |
24 | I created a fully searchable database of our available games called **[Game Night](https://game-night.csh.rit.edu)**. When landing on the home page, the web application lists out all of the games in the database, but since it could be a lot to scroll through, there are ways in which the results can be filtered down.
25 |
26 | The site provides a search field at the top to help users match games in the database that contain a certain keyword or string. If one happens to be familiar with regular expressions, they can use those in their queries. For example, searching with the query **b** will match all games that contain a **b** in their name, and searching with the regex query **^b** will match all games that start with a **b**. These queries are case-insensitive.
27 |
28 | In a situation where a number of people have gathered together and would like to figure out which games support that number of players, there is an additional search option for doing just that. By clicking on the button next to the search field, a small menu will appear with a dropdown selection for choosing the number of players. Since each game in the database has properties that represent the minimum and maximum number of players it supports, all the games returned in this query will be those that have the user-specified number of players fall within those ranges. This filtering option can be combined with the textual search option.
29 |
30 | Lastly, in that same menu there is a button for retrieving a random game from the database. This random option can be filtered by the aforementioned search options too.
31 |
32 | ## The RESTful API
33 |
34 | I made sure from the very beginning that **Game Night** would have a RESTful API exposed for CSH members to use. The API endpoint starts at **[https://game-night.csh.rit.edu/api](https://game-night.csh.rit.edu/api)**. Similar to the index page without a search query, it returns all of CSH's games, but in JSON format. The API can be filtered by adding on URL query parameters such as **name** and **players** to the end. An example would be **[https://game-night.csh.rit.edu/api?players=10](https://game-night.csh.rit.edu/api?players=10)**, which returns all games in JSON format that support 10 players. The API endpoint for retrieving a random game is also available at **[https://game-night.csh.rit.edu/api/random](https://game-night.csh.rit.edu/api/random)** and is filterable in the same way.
35 |
36 | ## The Technology Stack
37 |
38 | The primary tools I used to develop this web application were Python, Bootstrap 4, Flask and MongoDB. I had never used Flask before, but I was familiar with the similar Express framework used in Node.js. Going from Express to Flask, I grew to absolutely love the Flask framework even more than Express. I found its methodology of using decorators to handle responses to URL routes very elegant. I decided to use MongoDB over the more common MySQL or PostgreSQL for a few reasons:
39 |
40 | 1. It was an opportunity to learn something new.
41 | 2. Since I was only storing games in the database and there were no dependencies on other types of data, I did not need to make use of features offered by typical SQL-based relational database management systems such as foreign keys and joins.
42 | 3. MongoDB stores data in a format almost identical to JSON called BSON, meaning it is simpler to translate that to a format suitable for rendering in a view or returning in a RESTful API. Using a SQL-based RDMS typically requires an ORM.
43 |
44 | Like many other CSH services, **Game Night** is behind OIDC authentication.
45 |
46 | ## Future Plans
47 |
48 | A project like this has a lot of room for augmentation, and I plan on continuing work on it throughout the remainder of my time at RIT. Some features I've already thought about implementing are:
49 |
50 | 1. A way for users to upload games to the database through the web interface. Currently, only I can upload games.
51 | 2. Including games that are owned by individual CSH members. If the above feature were implemented, then a user uploading a game could specify whether they own it or it belongs to floor.
52 | 3. Keeping track of games that are up for trade or being borrowed. If a member would like to borrow a game to use outside of CSH for some time, there should be a way of updating that game's entry in the database to show that it's currently in use by someone.
53 |
54 | Any changes made will be pushed to the project's **[GitHub repository](https://github.com/mfrancis95/game-night)**.
55 |
56 | ## Special Thanks
57 |
58 | Thank you to Jordan for creating my OIDC client credentials and thank you to Zoe for helping me compile the initial list of the games.
--------------------------------------------------------------------------------
/_posts/2018-03-28-benchmarking-programing-languages.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: Benchmarking Programing Languages
4 | date: 2018-03-28
5 | categories: projects
6 | description: Testing the speed of separating axis theorem based collision detection in Python, Rust, and Kotlin
7 | author: Joel Eager
8 | image: /projects/benchmarking.png
9 | image-sm: /projects/benchmarking.png
10 | author-image: https://avatars1.githubusercontent.com/u/14286106?s=460&v=4
11 | author-bio: A 3rd year CS student at Computer Science House who enjoys messing with Python.
12 | author-email: joel@csh.rit.edu
13 | author-social:
14 | github: https://github.com/JoelEager
15 | ---
16 |
17 | Computers do math quite fast, but how fast? Well, the answer to that question changes quite significantly depending on
18 | the programming language being used.
19 |
20 | To explore this relationship I implemented a common collision detection algorithm called [separating axis theorem](https://gamedevelopment.tutsplus.com/tutorials/collision-detection-using-the-separating-axis-theorem--gamedev-169)
21 | in Python, Rust, and Kotlin. This algorithm uses linear algebra to check if two convex 2D polygons are overlapping.
22 | Since this is a linear algebra algorithm most of the work is repetitive arithmetic. This makes it a relatively good
23 | test of raw execution speed.
24 |
25 | Even before running the code I can expect [Python](https://en.wikipedia.org/wiki/Python_(programming_language)) to be
26 | the slowest since it's the only interpreted language being tested. [Rust](https://en.wikipedia.org/wiki/Rust_(programming_language)),
27 | on the other hand, is compiled down to machine code so it should be significantly faster. [Kotlin](https://en.wikipedia.org/wiki/Kotlin_(programming_language))
28 | should be somewhere in the middle since it's compiled but runs in the Java Virtual Machine instead of directly on the
29 | hardware.
30 |
31 | The metric I'll be measuring here is the wall-clock execution time. Note that this approach has an inherent amount of
32 | inaccuracy due to how operating systems handle process scheduling. However, it's also the metric that's most immediately
33 | understandable and comparable so it works well for this situation.
34 |
35 | The actual program that I'm using takes two objects and sets their center points 100 pixels away from each other. Then
36 | one object is moved towards the other in steps of 1 pixel at a time until the algorithm detects collision. This process
37 | is then repeated 10,000 times in order to build up a sufficiently long execution time to get an accurate comparision.
38 |
39 | Here are the results from running this test. Note how Kotlin and Rust have fairly similar results even though Kotlin
40 | runs in the JVM.
41 |
42 | | CPU used for the test | Time for Python | Time for Kotlin | Time for Rust |
43 | | --------------------- | --------------- | --------------- | ------------- |
44 | | Intel Core i7-8550U | 21.800 seconds | 0.308 seconds | 0.230 seconds |
45 | | AMD A10-6800K | 40.617 seconds | 0.767 seconds | 0.465 seconds |
46 |
47 | Now this is a pretty naive implementation. The two objects are 10 and 1 pixels across respectively so it takes a lot of
48 | iterations before they collide. This algorithm takes the most time to run when the objects aren't touching so it would
49 | be quite helpful if there was a way to skip over at least some of the iterations where they aren't touching.
50 |
51 | It turns out that it's trivial to calculate a rough estimate of the distance between the two objects by taking one point
52 | from each and applying the Pythagorean theorem. Now, this would be a very rough estimate since it doesn't take into
53 | account the rotation or shape of the objects in question. However, if that rough separation estimate is greater than the
54 | combined width of the two objects at their widest points then it can be assumed that the objects aren't touching. In
55 | all other cases the program would still have to run the collision detection algorithm as before to get an accurate
56 | result.
57 |
58 | With this optimization in play the execution times drop significantly. Note that due to the the inherent inaccuracy of
59 | the timing method used, the results for Rust on the two computers should be interpreted as roughly equal.
60 |
61 | | CPU used for the test | Time for Python | Time for Kotlin | Time for Rust |
62 | | --------------------- | --------------- | --------------- | ------------- |
63 | | Intel Core i7-8550U | 8.250 seconds | 0.145 seconds | 0.033 seconds |
64 | | AMD A10-6800K | 15.844 seconds | 0.346 seconds | 0.027 seconds |
65 |
66 | Even though Python is quite slow in comparison to Kotlin and Rust, it turns out that it's still easily fast enough to
67 | do this math in real time for a game. In fact the very Python code I tested here is used in game server of my [pyTanks](https://github.com/JoelEager/pyTanks.Server)
68 | project to check for collisions between the game objects. This just goes to show the trade off that exists with
69 | interpreted languages. While they may be more convenient to work with you're paying the price for that convenience in
70 | the execution speed.
71 |
72 | If you're interested in playing with these programs yourself you can find the Rust version [here](https://github.com/JoelEager/Rust-Collision-Detector)
73 | and the Kotlin version [here](https://github.com/JoelEager/Kotlin-Collision-Detector). The Python code is part of the
74 | server portion of my pyTanks project [here](https://github.com/JoelEager/pyTanks.Server). Specifically, the Python
75 | script that implements the algorithm is located [here](https://github.com/JoelEager/pyTanks.Server/blob/master/gameLogic/collisionDetector.py)
76 | in that repository. All of these repositories are under the MIT licence so if you'd like to make use of this code in one
77 | of your own projects you're more than welcome to.
78 |
--------------------------------------------------------------------------------
/_posts/2018-04-10-clades-cimicum.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: Clādēs Cimicum
4 | date: 2018-04-10
5 | categories:
6 | - debugger,c
7 | description: A small debugger that can read memory from another process.
8 | author: Collin Tod
9 | image: /projects/cDebugger.png
10 | image-sm: /projects/cDebugger.png
11 | author-image: https://avatars2.githubusercontent.com/u/9722413?s=400&u=58f02226ffe89fa4f69ad4a7f89f07efb1b72f4f&v=4
12 | author-bio: First year computer science student at Rochester Institute of Technology
13 | author-email: squables@csh.rit.edu
14 | author-social:
15 | github: https://github.com/squablyScientist
16 | ---
17 | # What Is It?
18 | This program, Clādēs Cimicum, (which means 'Bane of Bugs' in Latin) is a very small and simple debugger for interprocess debugging. This is slightly different from that of GDB, since GDB actually creates a child process when debugging. Cladēs Cimicum can read the memory of any running process, without having to be run in some special environment beforehand.
19 |
20 | # Why I Wrote It
21 | A while back, I found [this](https://github.com/scvalencia/MNIST_ASCII_challenge) challenge, and figured that I could do it. I started doing research into the best way to read the memory of another process, and found a few options:
22 |
23 | 1. Using ptrace to attach to the process and read its memory (This is what GDB does to a child proces)
24 | 2. Manually stopping the process and reading from its mem file in `/proc`
25 |
26 | I chose the latter of the two options because I wanted a bit of a challenge.
27 |
28 | # How To Use It
29 | Program usage
30 |
31 | ```sh
32 | debugger PID offset nbytes
33 | ```
34 |
35 | where `PID` is the process ID of the target process, `offset` is the address in the virtual memory of the process that you wish to read from, and `nbytes` is the number of bytes to read from the target process
36 |
37 | # How It Works
38 |
39 | First of all, a distinction must be made between the concept of a program, and the concept of a process. A program is the code that you write, and the binary file that it becomes when compiled, or the set of instructions executed as it is interpreted, or any number of other programming paradigms. In essence, it is the blueprint for behavior of the computer when that program is 'run'. A process on the other hand, is an individual instance of that program running. For example, you can have two instances of vim running, each their own separate process, but using the same program.
40 |
41 | As it turns out, a process on UNIX systems is nothing more than a collection of pseudo files stored in `/proc`. Everything about the process is stored in a folder within `/proc`, and the name of that folder for each process is the PID (Process ID) for that process. For example, if there is an instance of vim running with PID 413, everything about that specific process will be stored at `/proc/413`. In general, for any process, I will be referring to this location as `/proc/PID`.
42 |
43 | Among the numerous useful files and folders within `/proc/PID`, one stands out as immediately useful for the problem at hand: `/proc/PID/mem`. This file holds ALL of the virtual memory mapped to a process. (I am aware that it is not technically a file, but going into the mechanics of what a pseudo filesystem is is beyond the scope of the description of this project). Therefore, you should be able to read all of the memory of a running process just by opening that file right? Well yes, but it is slightly more involved than that.
44 |
45 | Firstly, the process that is to be examined (from here on out the target process) must not be running if you want to read the mem file. This is extrememly important in avoiding [race conditions.](https://en.wikipedia.org/wiki/Race_condition). My solution to this is to simply pause the execution of the process by utilizing signalling. Before I attempt to read the mem file, the target process is stopped with SIGSTOP. The once reading is done, the process is continued with SIGCONT.
46 |
47 | Secondly, you must be root to read the memory of another process in this way. It would be extremely unsafe for non-root or super users to be able to read the memory of any process on a machine at any time.
48 |
49 | Thirdly, and maybe most importantly, you must know the exact memory address of the memory you want to access. This is because attempting to accesss an address in virtual memory that is not mapped to a physical address by `/proc/PID/maps` will result in an IO error. This makes sense, because there is no physical representation of the area of memory attemting to be accessed. Thus, you must be extremely familiar with the target process in order to effectively use this method.
50 |
51 | # How I Solved the Captcha Problem
52 |
53 | The biggest challenge for this problem was actually finding the memory address of the answer to the captcha. Input is read in 1 by 1 so there is no array to immediately check against in the input function, where there is a blocking call to `scanf`. The solution I found however, does involve a simple array of ints that holds the answer. A stack frame always holds a pointer to the previous stack frame's stack pointer. The stack pointer is a register that holds a memory address to the last piece of memory that was requested to be allocated on the stack. This piece of memory just so happened, in the previous stack frame, to be an array holding the answer. Done. Using GDB to grab this value (There is absolutely a way to do this not using GDB, but there was not enought time to research how to search the stack for this exact value), I simply used the Clādēs Cimicum program to grab the memory at that pointer and print it out. This is the solution to the captcha.
54 |
55 | # What I Learned
56 |
57 | Pretty much everything that I know about the `/proc` folder, and how stack frames work.
58 |
59 | # The Project
60 | The project is hosted [here](https://github.com/squablyScientist/Clades-Cimicum). The `master` branch is the general debugger, whilst the `injection` branch is the solution for the captcha challenge.
61 |
--------------------------------------------------------------------------------
/membership/intro-process.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: page
3 | title: New Members
4 | active: membership-intro
5 | ---
6 |
7 |
8 |
9 |
10 |
11 |
Applying to CSH
12 |
13 | Incoming Freshman can apply through their RIT Housing Application, when asked about Special Interest Houses.
14 | Current students can either visit us on the 3rd floor of Fredericka Douglass Sprague Perry Hall, or submit a
15 | completed application to our Evaluations Director
16 | by emailing the filled out document to evals@csh.rit.edu
17 |
18 |
19 |
Note that RIT Housing caps us at 50 acceptances every summer, so if you weren't accepted at first, feel free to re-apply at any time!
20 | Applications are reviewed during the first week of each semester.
21 |
22 |
23 |
Introductory Process
24 |
25 | Once accepted to Computer Science House after the application stage, you are considered an introductory member.
26 | This means that you're invited to all our events, involved in our process, and considered to be a member in almost all cases.
27 |
28 |
29 | However, in order to become a full voting member, you need to complete our 6-week introductory process.
30 | The process should take no more than a few hours each week to complete.
31 | Our introductory process is defined in our Constitution and outlines completion of a few requirements:
32 |
33 |
34 |
35 |
Directorship Meetings
36 |
37 | You must attend an average of 1 directorship meeting for each week of the introductory process.
38 | This means that you must attend 6 directorship meetings before the end of the 6 week introductory period.
39 | There are between 7 and 10 directorship meetings occuring every week, each lasting about half an hour.
40 | During one, an Executive Board member conveys to house what they've done in their role recently and what they plan to do in the coming weeks.
41 |
42 |
43 |
44 |
Packet
45 |
46 | In order to keep CSH a tight-knit community, we want every member to meet and get to know every other member.
47 | In order to do this, we give each intro member a Packet — a list of all on-floor members and upperclassmen.
48 | Your job as an intro member is to seek out and meet as many of the upperclassmen as you can, and in return, they’ll sign your packet.
49 | The packet process takes place during the first two weeks of the semester, after which we’ll count all of the signatures that you’ve collected.
50 | If you get a passing percentage of signatures, congratulations! You’ll receive a CSH account and gain access to all of our house computer services.
51 | If not, there’s still hope! There is still more time in the intro process for you to continue meeting people, coming to events, and learning at seminars.
52 |
53 |
54 |
55 |
House Meetings
56 |
57 | There is a house meeting every Sunday at 7:15pm.
58 | You are required to attend all of them, as is every active upperclassman.
59 | During these, we go over upcoming and recent events, vote to spend money on member projects, and discuss changes to our Constitution.
60 |
61 |
62 |
63 |
Technical Seminars
64 |
65 | Over the 6 week introductory process, you must attend at least 2 technical seminars.
66 | These seminars are hosted on floor and go over a range of topics from Git and Python to more complex concepts like OpenGL or OpenShift.
67 |
68 |
69 |
70 |
Social Events
71 |
72 | All members are expected to attend some social events.
73 | Including camping trips, video game tournaments, movie nights, and much more, just participate in events on floor.
74 |
75 |
76 |
77 |
Evaluations
78 |
79 | At the 6-week mark, all of the upperclassmen meet and make a decision based on how well you’ve met the intro requirements.
80 | Members keep in mind your other responsibilities, such as other club meetings or classes, so don't worry if you're just shy of a requirement.
81 | If you’re voted in at this meeting, you become a full member!
82 |
12 | Projects are an integral part of the living, learning experience at
13 | Computer Science House. This is a small sample of notable projects
14 | that our members have created:
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
Drink/Snack
28 |
29 | Drink and Snack are two of CSH's oldest projects. Networked vending
30 | machines allow members to order items from any internet browser using
31 | a credits system. A timer can also be specified to delay the release
32 | of a purchased item.
33 |
47 | Schedule Maker allows RIT students to plan their schedule for upcoming
48 | semesters. Users simply enter their course numbers and custom events
49 | and a list of all schedules that match their parameters will be shown.
50 | Because it is so easy and simple, Schedule Maker is now used by over
51 | 90% of RIT students.
52 |
67 | Devcade is a fully custom arcade machine made by a team of over a dozen CSH members.
68 | Devcade is an arcade built for developers, by developers. The arcade cabinet, software,
69 | and games for Devcade were mainly built during the Fall 2022 semester and the project
70 | is still being maintained and updated.
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
Harold
85 |
86 | With Harold, every member of CSH gets their own theme song. After
87 | a user uploads either their song or playlist to a web app, all they
88 | have to do is touch their iButton or RFID tag (received upon
89 | membership) to the appropriate reader.
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
CSH Arcade
103 |
104 | Two CSH members built this arcade cabinet from scratch. It emulates
105 | many classic arcade games from varying consoles and supports
106 | multiplayer. A second cabinet featuring a custom-made platforming game
107 | was also built. Both machines, along with other arcade cabinets CSH
108 | has acquired, are housed in our Library.
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
InfoSys
122 |
123 | InfoSys is a multi-purpose display board located in our User Center.
124 | It is capable of displaying weather statistics, custom messages, and
125 | even real-time player data from video games.
126 |
127 |
128 |
129 |
130 |
131 |
--------------------------------------------------------------------------------
/_posts/2018-02-26-freeipa.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: post
3 | title: Deploying FreeIPA
4 | date: 2018-02-26 21:25:00
5 | categories: projects
6 | description: Migrating from custom LDAP/Kerberos setup to Red Hat's identity management platform.
7 | image: /projects/FreeIPA.png
8 | image-sm: /projects/FreeIPA.png
9 | author: Marc Billow
10 | author-image: https://2.gravatar.com/avatar/254e59006e0d907f97c529c62689c0e0?s=400
11 | author-bio: Networking and System Administration '18 at the Rochester Institute of Technology and System Administrator for Computer Science House
12 | author-email: mbillow@csh.rit.edu
13 | author-social:
14 | github: https://github.com/mbillow
15 | ---
16 |
17 | Before we begin, a bit about what FreeIPA actually is: FreeIPA, or Red Hat Identity Management, is a management interface and API built on top of several well-known, open source projects: 389 Directory Server, MIT Kerberos, DogTag for managing certificates and SSSD for client enrollment. The goal of the FreeIPA project is to create a cohesive, central, extensible, and easy to maintain user management and authentication system. FreeIPA provides an easy to use UI/UX for managing everything from user accounts, permissions, host based access controls to global sudo rules and certificate control. If you would like to play around with the interface, there is a public [demo instance](https://www.freeipa.org/page/Demo) available.
18 |
19 | ## Our Situation
20 | For years Computer Science House has relied on LDAP and Kerberos for user management and single sign-on. The culture and communication within our organization and the services we provide revolve around these accounts, so it is essential that the infrastructure around them is solid. We will go more in-depth on this in the next section, but we also store information about a person's membership in custom LDAP attributes, making LDAP a source-of-truth for many of the projects our members work on. This also presents the hurdle of properly handling ACLs to user data for service accounts used by these projects.
21 |
22 |
23 | FreeIPA also supports an ongoing initiative within CSH to have fully redundant services between our data center and RIT's datacenter across campus. `csh-ds01` and `csh-ds02` are both in our data center on different hypervisors and `csh-ds03` is on a hypervisor in the secondary data center.
24 |
25 |
26 |
27 | ## Handling Custom Attributes
28 |
29 | As aforementioned, we store a lot of our membership data in LDAP. We have groups for Active Membership, Current Students, and even a group for those who have been taught how to use the 3D printers (for regulating access). Also, we store information like social media accounts, RIT usernames, and drink balances for our on-floor vending machines. Over the years, we have expanded out LDAP schema to hold values like these, so it was important that this data get carried over. FreeIPA comes with a built-in LDAP migration tool, yet before we could migrate this data we needed to make sure the schema was there to support it.
30 |
31 |
32 |
33 | ### Extending the Schema
34 |
35 | Because FreeIPA is 389 Server under-the-hood, it is possible to write LDIFs that add custom objectTypes with new attributeTypes. By default, in our setup, each user gets assigned two more objectTypes: `ritStudent` and `cshMember`. `ritStudent` has attributes for fields like majors, minors, graduation year, RIT username, etc. `cshMember` allows us to store drink balances, membership dates, external accounts, etc.
36 |
37 |
38 |
39 | By default, FreeIPA schema gets loaded from `/etc/dirsrv/slapd-{REALM}/schema`. In this directory we defined both of the objectTypes and assigned them their respective attributeTypes. For example `ritStudent` has been included below:
40 |
41 |
42 |
43 | ```
44 |
45 | dn: cn=schema
46 |
47 | attributeTypes: ( 1.3.6.1.4.1.3319.8.501 NAME 'ritDn' SINGLE-VALUE EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch DESC 'RIT Account' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
48 |
49 | attributeTypes: ( 1.3.6.1.4.1.3319.8.502 NAME 'major' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch DESC 'RIT Major' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
50 |
51 | attributeTypes: ( 1.3.6.1.4.1.3319.8.503 NAME 'minor' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch DESC 'RIT Minor' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
52 |
53 | attributeTypes: ( 1.3.6.1.4.1.3319.8.504 NAME 'ritYear' SINGLE-VALUE EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch DESC 'RIT Year' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
54 |
55 |
56 |
57 | dn: cn=schema
58 |
59 | objectClasses: ( 1.3.6.1.4.1.3319.8.500 NAME 'ritStudent' AUXILIARY MAY ( ritDn $ major $ minor $ ritYear ) )
60 |
61 | ```
62 |
63 |
64 |
65 | ### Extending the UI/API
66 |
67 | Once the attributes are added to LDAP, you need to modify the API and Web UI they exist as well as the values that they are meant to hold.
68 |
69 |
70 |
71 | The API is written in Python and plugins are loaded from `/usr/lib/python2.7/site-packages/ipalib/plugins/`. Again, using `ritStudent` as an example:
72 |
73 |
74 |
75 | ```
76 | from ipalib.plugins import user
77 | from ipalib.parameters import Str
78 | from ipalib import _
79 |
80 | user.user.takes_params = user.user.takes_params + (
81 | Str('ritdn?',
82 | cli_name = 'ritdn',
83 | label = _('RIT Account'),
84 | ),
85 | Str('major*',
86 | cli_name = 'major',
87 | label = _('RIT Major'),
88 | ),
89 | Str('minor*',
90 | cli_name = 'minor',
91 | label = _('RIT Minor'),
92 | ),
93 | Str('rityear?',
94 | cli_name = 'rityear',
95 | label = _('RIT Year'),
96 | ),
97 | )
98 | ```
99 |
100 | Now that the CLI and API know about the attributes, we need to extend the Web UI to show the attributes we added. The frontend is written in Javascript and extensions are loaded from `/usr/share/ipa/ui/js/plugins/` where each extension has a folder with a Javascript file in it. Example: `/usr/share/ipa/ui/js/plugins/rit-student/rit-student.js`
101 |
102 |
103 |
104 | ```
105 | define([
106 | 'freeipa/phases',
107 | 'freeipa/user'
108 | ],
109 | function(phases, user_mod) {
110 | // helper function
111 | function get_item(array, attr, value) {
112 | for (var i = 0, l = array.length; i < l; i++) {
113 | if (array[i][attr] === value) return array[i];
114 | }
115 | return null;
116 | }
117 | var student_plugin = {};
118 | student_plugin.add_student_pre_op = function() {
119 | var facet = get_item(user_mod.entity_spec.facets, '$type', 'details');
120 | var section = get_item(facet.sections, 'name', 'identity');
121 |
122 | section.fields.push({
123 | name: 'ritdn',
124 | label: 'RIT Account'
125 | });
126 |
127 | section.fields.push({
128 | name: 'major',
129 | label: 'RIT Major',
130 | $type: 'multivalued'
131 | });
132 |
133 | section.fields.push({
134 | name: 'minor',
135 | label: 'RIT Minor',
136 | $type: 'multivalued'
137 | });
138 |
139 | section.fields.push({
140 | name: 'rityear',
141 | label: 'RIT Year'
142 | });
143 |
144 | return true;
145 |
146 | };
147 | phases.on('customization', student_plugin.add_student_pre_op);
148 | return student_plugin;
149 | });
150 | ```
151 |
152 |
153 |
154 | These Python and Javascript plugins need to be replicated to each IPA server in order for the fields to be accessible through those servers. Schema though, is automatically replicated.
155 |
156 |
157 |
158 | ## FreeRADIUS and Wireless
159 |
160 | Computer Science House administers its own wireless network which uses WPA2 Enterprise authentication through RADIUS authentication over TLS. In the past we have used a custom script which used MD4 hashes stored in Kerberos and handled the MSCHAPv2 challenge response protocol manually. Though this solution worked, it was not well documented and difficult to troubleshoot. FreeIPA though has the ability to support cross-domain trusts with Active Directory out-of-the-box. We used this feature to have IPA generate the necessary hashes, store them in LDAP, and then gave FreeRADIUS's service account the ability to view this field.
161 |
162 |
163 |
164 | This greatly simplifies our FreeRADIUS configuration since we can just use the default LDAP module and point it at the `ipaNtHash` attribute of the user trying to authenticate.
165 |
166 |
167 |
168 | ## Deployment
169 |
170 | Since we use Puppet as our configuration management platform, we decided that to efficiently enroll our existing hosts, we would push out a manifest that installed the `freeipa-client` package and ran `ipa-client-install` for us with the proper parameters. The easiest way to do this, that I could think of, was to create a `puppet` account in FreeIPA and give the necessary permissions to enroll hosts and create host objects. (Both operations are necessary to enroll a new host from scratch.) Our Puppet environments are controlled by a Git repo using r10k with Heira and secrets are encrypted using Heira-Eyaml. We are able to automatically enroll hosts in our domain after: configuring the user, encrypting the password in the Heira config, and configuring the [ipaclient](https://forge.puppet.com/joshuabaird/ipaclient) puppet module. This allows for the rapid bootstrapping of a new server with a single Puppet run.
171 |
--------------------------------------------------------------------------------
/about/eboard.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: page
3 | title: Executive Board
4 | active: about-eboard
5 | ---
6 |
7 |
8 |
9 |
10 |
11 |
12 | The executive board is responsible for ensuring the functions integral to the CSH experience go off
13 | as smoothly as possible.
14 | Elected at the end of every academic year, they volunteer their time to help make floor an even
15 | better place to be.
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
Chair
28 |
Isaac Ingram
29 |
30 | The Chair of CSH serves as the head of E-Board, supervising the activities of the directors and
31 | presiding over our weekly house meetings.
32 | They are also the primary spokesperson for the House, representing the interests of our
33 | members in communications with RIT and the rest of the world.
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
Evaluations
46 |
Ian Kopke
47 |
48 | Evaluations is responsible for connecting with the RIT student community, as well as
49 | organizing the process of screening, accepting, and welcoming new members.
50 | Members wouldn't be here without evals!
51 |
52 |
53 | If you would like to visit or tour the floor, let the Eval Director know and
54 | they can arrange this.
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
Financial
67 |
Matthew Wilkins
68 |
69 | Financial is responsible for managing CSH's finances, collecting semesterly member
70 | dues, and hatching new fundraising schemes.
71 | All of our money goes towards new resources and project components for members to use; CSH is a
72 | registered non-profit organization with an annual self-generated budget.
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
House History
85 |
Logan Endes
86 |
87 | The primary responsibility of the History director is keeping the line of communication between CSH
88 | and our alumni open.
89 | We believe members should have a well-developed understanding of House's origins and
90 | accomplishments.
91 | History keeps the past alive through the yearbook, Coredump newsletter, floor displays, archiving,
92 | updating the media database, and managing alumni relations.
93 | History also coordinates alumni storytelling nights and other traditional events.
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
House Improvements
106 |
Shaela Spring
107 |
108 | House Improvements is responsible for keeping our living space respectable and
109 | comfortable.
110 | They delegate projects that improve the physical aspects of floor, such as painting,
111 | cleaning, building, and organizing House's resources.
112 | While we may not be the tidiest group of people, we like to take care of our floor, and it shows.
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
OpComm
125 |
Tyler Allen
126 |
127 | The OpComm director, together with a group of technically skilled members known as RTPs, is
128 | responsible for maintaining CSH's servers and network infrastructure.
129 | Becoming an RTP allows members to develop and practice skills that are essential for working in
130 | computing fields.
131 | If you have any questions about House's technical resources, the OpComm director should be your
132 | first stop!
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
Research and Development
145 |
Cole Stowell & Will Hellinger
146 |
147 | R&D is responsible for organizing seminars and assisting with technical projects, with the goal of
148 | encouraging members to learn new skills and gain experience.
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
Social
161 |
Grant Hawerlander & Conner Meagher
162 |
163 | Social is responsible for planning and running social events for our members, such as
164 | Welcome Back, movie nights, and other events on floor and around Rochester.
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
Public Relations
177 |
Ava McCaffrey
178 |
179 | Public Relations is responsible for maintaining CSH's public facing image, primarily
180 | through the management of our various social media accounts.
181 | They work to share all information regarding the organization, and the goings-on therein,
182 | as well as contacting various outside parties, including but not limited to employers, students, and
183 | media outlets to share what we're up to! Follow us on:
184 | Twitter,
185 | Instagram, and
186 | Facebook.
187 |
12 | Computer Science House has been fortunate enough to have a myriad of very generous sponsors. Without their support it would be impossible to learn, grow, and innovate as we do.
13 |
Since 1976, Computer Science House has provided a revolutionary living and learning environment for its members. With unique facilities, an emphasis on hands-on learning, and a strong social atmosphere, CSH helps its members grow as professionals and more.