# Project export: TutorPages

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: TreeHacks 2024
- Tagline: Tutoring services require some technical infrastructure, without which the they can seem amateurish and disorganized. Let's make a plug-and-play version that works for everyone right out of the box.
- Devpost: https://devpost.com/software/tutorpages
- GitHub: https://github.com/Rubemat20/tutorPages
- Demo: https://rubemat20.github.io/tutorPages/
- Team: 2 GitHub contributor(s) — Matthew Rubenstein (135 commits), maxmandel (2 commits)

## Devpost submission (written by the team)

### Inspiration

I'm involved in a community service tutoring club at the University of Chicago called Phoenix Tutoring. We work with CPS students in the south-side Chicago community, and I've always found it really rewarding. Lately I've been trying to come up with a way to streamline our process with some technical infrastructure.

### What it does

Plug-and-Play Tutoring - Instant set up of a community service tutoring program at any college campus. Tutoring programs require a level of technical infrastructure, in particular: A mechanism for enrolling students A mechanism for undergrads/grads to apply to be tutors A mechanism to match tutors and students, once enrolled and admitted A calendar to track when tutoring sessions will occur A good technical infrastructure would also include certain ‘luxuries’, including: Automated reminder emails to tutors and tutees based on the calendar A mechanism to collect basic analytics: most in-demand subjects, times, etc. A mechanism to collect feedback A mechanism to re-match tutors and tutees, on a semester to semester basis, based on said feedback The idea of Plug-and-Play Tutoring/TutorPages is to provide a black box that requires only basic, surface-level inputs from the users and abstracts away all technical complexity, providing features like this as well as room to grow more and build up new capabilities. This would lower the barrier to entry to creating quality, functional tutoring community service programs at any and every higher-education institution.

### How we built it

For our Treehacks project, we're building a website allowing the user to showcase all tutors and students in their program. We're also putting together a matching algorithm to match tutors to students optimally by distances between n-dimensional preference vectors.

### Challenges we ran into

Creating dynamically updated websites has been challenging, as we're fairly new to web development.

### Accomplishments we're proud of

While we've run into some technical challenges, we're proud to be working on a project with the intent to make community service easier and more streamlined across the country. We're optimistic about our approach for a matching algorithm and we're proud to have a coherent, condensed project.

### What we learned

Though we haven't moved forward with implementing our website with it, we've learned a lot about the Reflex API. We've also learned a lot about github pages, which we will be using.

### What's next

Though in the 36hr format of Treehacks we of course can't perfectly implement every niche detail of a product like TutorPages, in the future we'll be continuing to work on it. As we've planned it out there's an ever-growing depth - for example, one key element we'd like to add is log-in and private access for different members of the organization, tutors, parents, students, admin, etc. The Matching Algorithm Taking lists of lists of tutor and tutee information read in by text from our student enrollment/tutor application forms, we make Tutor and Tutee python objects. For a total offering of n subjects and k times, we provide helper functions to 1) take the distance formula on two n-dimensional vectors/points and 2) find overlaps out of lists of <= k times of availability. Using these helpers, we match every tutee to one tutor, with only tutors having the possibility of remaining unmatched. We do this as follows: after making sure the potential-match tutor and tutee are available at the same time, we optimize for similarity of subject preference vectors: tutors that are most comfortable tutoring a given subject are paired with students most in need of help with that subject. Finally, we produce Session objects from our matching dictionary, and store them. We should be left with a grouping of Session objects which can be queried for information about the tutor and tutee, the time, subjects being tutored, and so on.

## README (from the GitHub repository)

## Inspiration
I'm involved in a community service tutoring club at the University of Chicago called Phoenix Tutoring. We work with CPS students in the south-side Chicago community, and I've always found it really rewarding. Lately I've been trying to come up with a way to streamline our process with some technical infrastructure.

## What it does
Plug-and-Play Tutoring - Instant set up of a community service tutoring program at any college campus. Tutoring programs require a level of technical infrastructure, in particular:
- A mechanism for enrolling students
- A mechanism for undergrads/grads to apply to be tutors
- A mechanism to match tutors and students, once enrolled and admitted
- A calendar to track when tutoring sessions will occur

A good technical infrastructure would also include certain ‘luxuries’, including:
- Automated reminder emails to tutors and tutees based on the calendar
- A mechanism to collect basic analytics: most in-demand subjects, times, etc.
- A mechanism to collect feedback
- A mechanism to re-match tutors and tutees, on a semester to semester basis, based on said feedback

The idea of Plug-and-Play Tutoring/TutorPages is to provide a black box that requires only basic, surface-level inputs from the users and abstracts away all technical complexity, providing features like this as well as room to grow more and build up new capabilities.

## How we built it
For our Treehacks project, we're building a website allowing the user to showcase all tutors and students in their program. We're also putting together a matching algorithm to match tutors to students optimally by distances between n-dimensional preference vectors.

## Challenges we ran into
Creating dynamically updated websites has been challenging, as we're fairly new to web development.

## Accomplishments that we're proud of
While we've run into some technical challenges, we're proud to be working on a project with the intent to make community service easier and more streamlined across the country. We're optimistic about our approach for a matching algorithm and we're proud to have a coherent, condensed project.

## What we learned
Though we haven't moved forward with implementing our website with it, we've learned a lot about the Reflex API. We've also learned a lot about github pages, which we will be using. 

## What's next for TutorPages
Though in the 36hr format of Treehacks we of course can't perfectly implement every niche detail of a product like TutorPages, in the future we'll be continuing to work on it. As we've planned it out there's an ever-growing depth - for example, one key element we'd like to add is log-in and private access for different members of the organization, tutors, parents, students, admin, etc.

## The Matching Algorithm
Taking lists of lists of tutor and tutee information read in by text from our student enrollment/tutor application forms, we make Tutor and Tutee python objects. For a total offering of n subjects and k times, we provide helper functions to 1) take the distance formula on two n-dimensional vectors/points and 2) find overlaps out of lists of <= k times of availability. Using these helpers, we match every tutee to one tutor, with only tutors having the possibility of remaining unmatched. We do this as follows: after making sure the potential-match tutor and tutee are available at the same time, we optimize for similarity of subject preference vectors: tutors that are most comfortable tutoring a given subject are paired with students most in need of help with that subject. Finally, we produce Session objects from our matching dictionary, and store them. We should be left with a grouping of Session objects which can be queried for information about the tutor and tutee, the time, subjects being tutored, and so on.

Getting Started with TutorPages
=========================
## Useful Links
 - Tutor Signup form: https://bit.ly/tutorPagestutor
 - Student Signup form: https://bit.ly/tutorPagesStudent
## How to use
 - Fork the repo
 - Replace `your-email@domain.com` in `_config.yml` with your email address. Refer to [formspree](http://formspree.io/) for more information.
 - Clone the repo onto your local machine
 - Download the results of your tutor signup form and student signup form (see above), and replace the current tutorinfo.xlsx and studentinfo.xlsx forms in your local repo. Open and run the pipeline.py file from the pythonfiles folder on your local machine, and your pairings will appear!

   
# Setting Up a Virtual Environment and Installing Required Packages

## Step 1: Install Conda

If you haven't installed Conda yet, you can download and install Miniconda or Anaconda from the official website: [Miniconda](https://docs.conda.io/en/latest/miniconda.html) | [Anaconda](https://www.anaconda.com/products/distribution).

## Step 2: Create a Virtual Environment

Open a terminal or command prompt and create a new virtual environment using Conda. Replace `<env_name>` with your desired environment name.

```bash
conda create --name <env_name> python=3.8
```

Activate the virtual environment:

- On Windows:
  ```bash
  conda activate <env_name>
  ```

- On macOS and Linux:
  ```bash
  source activate <env_name>
  ```

## Step 3: Install Required Packages

Navigate to the directory containing your `requirements.txt` file. Then, use pip to install the required packages:

```bash
pip install -r requirements.txt
```

Replace `requirements.txt` with the actual name of your requirements file if it's different.

## Step 4: Verify Installation

To verify that the packages were installed correctly, you can check the list of installed packages in your virtual environment:

```bash
pip list
```

## Step 5: Deactivate the Virtual Environment

Once you're done working in the virtual environment, you can deactivate it:

```bash
conda deactivate
```


Jekyll theme based on [Freelancer bootstrap theme ](http://startbootstrap.com/template-overviews/freelancer/)


---------
For more details, read the [documentation](http://jekyllrb.com/)


## Detected evidence (automated analysis)

Indexed codebase: 58 recognized source files, 650 KB.
- CSS (language) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- PHP (language) — detected in the code
- Python (language) — detected in the code

## Codebase structure (from repository index)

### Files (70 of 70)

```
_config.yml
_includes/about.html
_includes/addtutor.html
_includes/algo.html
_includes/code.html
_includes/contact_disqus.html
_includes/contact_static.html
_includes/contact.html
_includes/css/bootstrap.min.css
_includes/css/main.css
_includes/footer.html
_includes/head.html
_includes/header.html
_includes/js_disqus.html
_includes/js.html
_includes/modals.html
_includes/nav.html
_includes/portfolio_grid.html
_includes/student_grid.html
_layouts/default.html
_layouts/style.css
_layouts/tutor.html
_posts/2024-02-17-project-1.markdown
_posts/2024-02-17-project-2.markdown
_posts/2024-02-17-project-3.markdown
_posts/2024-02-17-project-4.markdown
_posts/2024-02-17-project-5.markdown
_posts/2024-02-17-project-6.markdown
.github/ISSUE_TEMPLATE/bug_report.md
.gitignore
.travis.yml
addtutor.md
css/font-awesome/css/all.css
css/font-awesome/css/all.min.css
feed.xml
freelancer-theme-jekyll.gemspec
Gemfile
index.html
js/bootstrap.js
js/bootstrap.min.js
js/cbpAnimatedHeader.js
js/cbpAnimatedHeader.min.js
js/classie.js
js/contact_me_static.js
js/contact_me.js
js/freelancer.js
js/jqBootstrapValidation.js
js/jquery-1.11.0.js
js/jquery.easing.min.js
LICENCE
mail/contact_me.php
pythonFiles/pipeline.py
pythonFiles/studentUpload.py
pythonFiles/Treehacks_matching_algo/matching.py
pythonFiles/Treehacks_matching_algo/session.py
pythonFiles/Treehacks_matching_algo/tutees.py
pythonFiles/Treehacks_matching_algo/tutors.py
pythonFiles/tutorUpload.py
Rakefile
README.md
requirements.txt
signups.md
students.html
students/student_Ruby.md
students/student_Tanner.md
style.css
tutor_1.md
tutors/tutor_Bauer.md
tutors/tutor_Smith.md
tutorUpload.py
```

### Dependencies

- requirements.txt: git@~=3.1.42, openpyxl@~=3.1.2

### Recent commits (newest first)

- Update README.md
- Update _config.yml
- Update _config.yml
- Update code.html
- Update about.html
- Update nav.html
- Update students.html
- Update nav.html
- Create students.html
- Add files via upload
- Delete img/portfolio/code5.jpg
- Update 2024-02-17-project-1.markdown
- Update 2024-02-17-project-5.markdown
- Rename 2014-07-14-project-5.markdown to 2024-02-17-project-5.markdown
- Update and rename 2014-07-16-project-3.markdown to 2024-02-17-project-3.markdown
- Update and rename 2014-07-17-project-2.markdown to 2024-02-17-project-2.markdown
- Update and rename 2014-07-15-project-4.markdown to 2024-02-17-project-4.markdown
- Update algo.html
- Update default.html
- Merge branch 'master' of https://github.com/Rubemat20/tutorPages

## Key source files (fetched from GitHub, selected and truncated for size)

### addtutor.md

```markdown
---
layout: default
---

```

### tutor_1.md

```markdown
1
2024-02-17 16:52:21
2024-02-17 16:53:11
anonymous
None
None
Jack Smith
2000-05-02 00:00:00
UCLA
Sophomore
jacksmith@gmail.com
1234567890
Debit/Credit card
Jack Smith
Yes
Yes
None
8
6
8
6
4
3
```

### requirements.txt

```
openpyxl~=3.1.2
git~=3.1.42
```

### Gemfile

```
source "https://rubygems.org"
gemspec

```

### style.css

```css
---
layout: style
---
```

### index.html

```html
---
layout: default
---
```

### .travis.yml

```yaml
language: ruby
script:
  - gem install jekyll bundler
  - bundle install
  - bundle exec rake test
  - bundle exec jekyll build
cache: bundler

```

### _config.yml

```yaml
# Site settings
title: TutorPages
email: youremail@domain.edu
url: https://rubemat20.github.io/tutorPages/
description: "Your solution for creating a tutoring franchise in seconds"
keywords: "tutor, franchise, student, algorithm, popup"
skills: "Tutoring Setup - Algorithmic Pairing - Ease of Access"
meta_author: Mandel Max

# Google webmaster tools
google_verify:

# https://ssl.bing.com/webmaster/configure/verify/ownership Option 2 content= goes here
bing_verify:

# Contact form:
# - static : pass through formspree.io to validate email sending
# - disqus : replace contact form by disqus thread
# - comment the line below if you want to stick with the default PHP contact form
contact: static

# If you use disqus you need disqus shortname
# https://help.disqus.com/customer/portal/articles/466208
disqus_shortname: myshortname

# Color settings (hex-codes without the leading hash-tag)
color:
  primary: 18bc9c #80B3FF
  primary-rgb: "24,288,156" #"128,179,255"
  secondary: 2c3e50 #FD6E8A
  secondary-dark: 233140 #A2122F

# Footer settings
footer:
  copyright: Stanford TreeHacks
  location: Location
  social: Around the Web
  credits: Credits
address:
  - line: University of Chicago
  
# Social networks usernames (many more available: google-plus, flickr, dribbble, pinterest, instagram, tumblr, linkedin, etc.)
social:
  - title: github
    url: https://github.com/Rubemat20/tutorPages/

# Credits content
credits: 'TutorPages is a free to use, open source template, created using Freelancer, by <a href="http://startbootstrap.com">Start Bootstrap</a>.'

# Build settings
markdown: kramdown
permalink: pretty

#for posts
defaults:
  - scope:
      path: ""
      type: "posts"
    values:
      permalink: ""

# Collections
collections_dir: ""
collections:
  tutors:
    output: true
    permalink: "/tutors/:modal-id/"
    directory: "tutors"
  students:
    output: true
    permalink: "/students/:modal-id/"
    directory: "students"

```

### tutorUpload.py

```python
import os
from datetime import date
from git import Repo

def read_tutor_info(folder_path):
    tutor_info_list = []
    for file_name in os.listdir(folder_path):
        if file_name.endswith('.txt'):
            with open(os.path.join(folder_path, file_name), 'r') as file:
                tutor_info = file.read()
                tutor_info_list.append(tutor_info.strip())
    return tutor_info_list

def increment_modal_id(tutor_info_list):
    new_tutor_info_list = []
    for i, tutor_info in enumerate(tutor_info_list, start=1):
        new_tutor_info = tutor_info.replace('modal-id: 6', f'modal-id: {i}')
        new_tutor_info_list.append(new_tutor_info)
    return new_tutor_info_list

def generate_image_filename(tutor_name):
    first_name = tutor_name.split()[0].lower()  # Assuming tutor name is in the format "First Last"
    return f'{first_name}.png'

def create_markdown_files(tutor_info_list):
    today = date.today().strftime('%Y/%m/%d')
    file_names = []
    for i, tutor_info in enumerate(tutor_info_list, start=1):
        lines = tutor_info.split('\n')
        tutor_name = lines[6].split(': ')[1]
        lines[1] = f"modal-id: {i}"
        lines[2] = f"date: {today}"
        lines[3] = f"img: {generate_image_filename(tutor_name)}"
        lines[8] = f"subject(s): {lines[8].split(': ')[1]}"  # Assuming subject(s) field is already in the correct format
        file_names.append(f'tutor_{i}.md')
        with open(f'tutor_{i}.md', 'w') as file:
            file.write('\n'.join(lines))
    return file_names
def push_to_github(repo_path, file_names, commit_message):
    repo = Repo(repo_path)
    for file_path in file_names:
        repo.index.add([file_path])
    repo.index.commit(commit_message)
    origin = repo.remote(name='origin')
    origin.push()

def main():
    # Define folder containing .txt files
    folder_path = 'folder_of_txt_files'

    # Read student names from .txt files
    tutor_list = read_tutor_info(folder_path)

    # Create Markdown file listing student names
    file_names = create_markdown_files(tutor_list)
    current_dir = os.getcwd()
    repo_path = None
    while True:
        # Check if the .git directory exists in the current directory
        if os.path.isdir(os.path.join(current_dir, '.git')):
            repo_path = current_dir
            break
        # Move up one directory
        current_dir = os.path.dirname(current_dir)
        # Stop if we've reached the root directory
        if current_dir == '/':
            break

    # Push Markdown file to GitHub
    push_to_github(repo_path, file_names, 'Add list of tutors')

if __name__ == "__main__":
    main()
```

### feed.xml

```xml
---
layout: null
---
<?xml version="1.0" encoding="utf-8"?>
{% if page.xsl %}
  <?xml-stylesheet type="text/xml" href="{{ '/feed.xslt.xml' | absolute_url }}"?>
{% endif %}
<feed xmlns="http://www.w3.org/2005/Atom" {% if site.lang %}xml:lang="{{ site.lang }}"{% endif %}>
  <generator uri="https://jekyllrb.com/" version="{{ jekyll.version }}">Jekyll</generator>
  <link href="{{ page.url | absolute_url }}" rel="self" type="application/atom+xml" />
  <link href="{{ '/' | absolute_url }}" rel="alternate" type="text/html" {% if site.lang %}hreflang="{{ site.lang }}" {% endif %}/>
  <updated>{{ site.time | date_to_xmlschema }}</updated>
  <id>{{ '/' | absolute_url | xml_escape }}</id>

  {% if site.title %}
    <title type="html">{{ site.title | smartify | xml_escape }}</title>
  {% elsif site.name %}
    <title type="html">{{ site.name | smartify | xml_escape }}</title>
  {% endif %}

  {% if site.description %}
    <subtitle>{{ site.description | xml_escape }}</subtitle>
  {% endif %}

  {% if site.author %}
    <author>
        <name>{{ site.author.name | default: site.author | xml_escape }}</name>
      {% if site.author.email %}
        <email>{{ site.author.email | xml_escape }}</email>
      {% endif %}
      {% if site.author.uri %}
        <uri>{{ site.author.uri | xml_escape }}</uri>
      {% endif %}
    </author>
  {% endif %}

  {% assign posts = site.posts | where_exp: "post", "post.draft != true" %}
  {% for post in posts limit: 10 %}
    <entry{% if post.lang %}{{" "}}xml:lang="{{ post.lang }}"{% endif %}>
      <title type="html">{{ post.title | smartify | strip_html | normalize_whitespace | xml_escape }}</title>
      <link href="{{ post.url | absolute_url }}" rel="alternate" type="text/html" title="{{ post.title | xml_escape }}" />
      <published>{{ post.date | date_to_xmlschema }}</published>
      <updated>{{ post.last_modified_at | default: post.date | date_to_xmlschema }}</updated>
      <id>{{ post.id | absolute_url | xml_escape }}</id>
      <content type="html" xml:base="{{ post.url | absolute_url | xml_escape }}">{{ post.content | strip | xml_escape }}</content>

      {% assign post_author = post.author | default: post.authors[0] | default: site.author %}
      {% assign post_author = site.data.authors[post_author] | default: post_author %}
      {% assign post_author_email = post_author.email | default: nil %}
      {% assign post_author_uri = post_author.uri | default: nil %}
      {% assign post_author_name = post_author.name | default: post_author %}

      <author>
          <name>{{ post_author_name | default: "" | xml_escape }}</name>
        {% if post_author_email %}
          <email>{{ post_author_email | xml_escape }}</email>
        {% endif %}
        {% if post_author_uri %}
          <uri>{{ post_author_uri | xml_escape }}</uri>
        {% endif %}
      </author>

      {% if post.category %}
        <category term="{{ post.category | xml_escape }}" />
      {% endif %}

      {% for tag in post.tags %}
        <category term="{{ tag | xml_escape }}" />
      {% endfor %}

      {% if post.excerpt and post.excerpt != empty %}
        <summary type="html">{{ post.excerpt | strip_html | normalize_whitespace | xml_escape }}</summary>
      {% endif %}

      {% assign post_image = post.image.path | default: post.image %}
      {% if post_image %}
        {% unless post_image contains "://" %}
          {% assign post_image = post_image | absolute_url | xml_escape  %}
        {% endunless %}
        <media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="{{ post_image }}" />
      {% endif %}
    </entry>
  {% endfor %}
</feed>

```

[44 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]