# Project export: MedEasy

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: We empower patients by increasing accessibility and understandability of medical health records.
- Devpost: https://devpost.com/software/medeasy-zqmd9g
- GitHub: https://github.com/gr125/treehacks24
- Video: https://www.youtube.com/embed/hbdI4dNGEOA?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 4 GitHub contributor(s) — gr125 (31 commits), YheChen (29 commits), Kwang316 (17 commits), Tango117 (7 commits)

## Devpost submission (written by the team)

### Inspiration

One of the key problems with today's healthcare systems is the lack of patient agency. Patients rarely access their medical health records: medical health records can be cumbersome to obtain and difficult to understand. As a result, MedEasy was developed with the objective of assisting individuals who have trouble viewing and understanding their personal medical records.

### What it does

MedEasy offers a simple platform for patients to access information about their medical health records and their current health condition. Patients can log in to the platform, where they are presented with a summary of important details like relevant care plans, current conditions, and vitals. Patients can then understand more about their condition through the chat interface on the platform; they can ask follow up questions regarding their health and a chatbot will explain the answers to them in an easily understable way.

### How we built it

We used Synthea, a Synthetic Patient Generation tool to generate realistic electronic health records in the form of CSV files. We then processed these CSV files to glean relevant information, and fed a textual representation of the electronic health record to a Code Llama LLM using together.ai's API, prompting it to simplify the input so it can be better understood. We also used together.ai's API and the Code Llama LLM to create a chatbot-like interface on the website, where patients can ask follow-up questions and the LLM will answer them to the best of its abilities. We created a front-end website using React.JS and connected our code to the website using the Python Flask module.

### Challenges we ran into

We had difficulties finding a reliable free database solution for our product, and ended up using a local postgresql database for EMR tabular data. Additionally, we struggled with implementing the website since most of our team had very little experience with front-end coding. Lastly, we had many concerns related to resolving dependencies and using virtual environments, as our front-end platform was very sensitive to them.

### Accomplishments we're proud of

We are proud to announce that we brainstormed an idea given real issues in the world, and worked hard at it, which resulted in us creating a possible solution to these issues.

### What we learned

Through the long process of brainstorming, developing and testing MedEasy, we learned invaluable time-management, collaboration and technical skills. In addition, we learned that given an idea, it is possible for us to create that idea given enough effort.

### What's next

Given how rapidly artificial intelligence is developing, MedEasy is only the beginning of future developments. With enough time, AI technology will be able to process tremendous amounts of information that no human could in a lifetime, which will result in scientific breakthroughs that benefit society as a whole. MedEasy has the potential to empower patients by giving them the ability to understand more about their health and have better access to electronic health records. During TreeHacks, one of the ideas we experimented with was using voice-to-text software to allow people to "talk" to LLMs. This idea has the potential to significantly increase the population that MedEasy can serve, such as the elderly and people with debilitating health conditions.

## README (from the GitHub repository)

# EHR Patient Summarizer and Advisor

## Introduction
This project applies Together.ai API to various simulated patient data to summarize health records and advise individuals. It's designed for patient use to directly obtain more information about their electronic health records (EHR) and provides general medical advise based on their history.
## Features
- Together.ai

## Installation
Clone the repository and open `index.html` in your browser to start exploring the 3D scene.

```
git clone https://github.com/gr125/treehacks23.git
```
## Usage


## Structure and Components
- 

## Detailed Functionality
- 

## Contributing
Contributions to enhance or expand the project are welcome. Feel free to fork the repository, make changes, and submit pull requests.

## License

## Acknowledgments

## Contact
For more information and updates, ...


## Detected evidence (automated analysis)

Indexed codebase: 19 recognized source files, 45 KB.
- CSS (language) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- SQL (language) — detected in the code
- Flask (technology) — claimed on Devpost, not found in the code
- OpenAI (technology) — claimed on Devpost, not found in the code
- PostgreSQL (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (33 of 33)

```
chatbot/telegram_elevenslb_voice
chatbot/telegram_elevenslb_voice_no_teleint
chatbot/test_together_api.py
chatbot/voice_only_LLM
postgresql/generate_tables.sql
postgresql/get_patient_info.py
postgresql/output.txt
README.md
treehacks 2/package.json
treehacks 2/react-login-demo/auth-server/.gitignore
treehacks 2/react-login-demo/auth-server/app.js
treehacks 2/react-login-demo/auth-server/database.json
treehacks 2/react-login-demo/frontend/.env
treehacks 2/react-login-demo/frontend/.gitignore
treehacks 2/react-login-demo/frontend/backend/.flaskenv
treehacks 2/react-login-demo/frontend/backend/base.py
treehacks 2/react-login-demo/frontend/key.env.local
treehacks 2/react-login-demo/frontend/package.json
treehacks 2/react-login-demo/frontend/public/index.html
treehacks 2/react-login-demo/frontend/public/manifest.json
treehacks 2/react-login-demo/frontend/public/robots.txt
treehacks 2/react-login-demo/frontend/README.md
treehacks 2/react-login-demo/frontend/src/App.css
treehacks 2/react-login-demo/frontend/src/App.js
treehacks 2/react-login-demo/frontend/src/App.test.js
treehacks 2/react-login-demo/frontend/src/home.css
treehacks 2/react-login-demo/frontend/src/home.js
treehacks 2/react-login-demo/frontend/src/index.css
treehacks 2/react-login-demo/frontend/src/index.js
treehacks 2/react-login-demo/frontend/src/login.css
treehacks 2/react-login-demo/frontend/src/login.js
treehacks 2/react-login-demo/frontend/src/reportWebVitals.js
treehacks 2/react-login-demo/frontend/src/setupTests.js
```

### Dependencies

- treehacks 2/package.json: dotenv@^16.4.4
- treehacks 2/react-login-demo/frontend/package.json: @clerk/clerk-react@^4.30.5, @testing-library/jest-dom@^5.16.5, @testing-library/react@^13.4.0, @testing-library/user-event@^13.5.0, axios@^1.6.7, dotenv@^16.4.4, react@^18.2.0, react-dom@^18.2.0, react-router-dom@^6.8.1, react-scripts@5.0.1, web-vitals@^2.1.4

### Recent commits (newest first)

- Merge branch 'main' of https://github.com/gr125/treehacks24
- remove keys
- Update telegram_elevenslb_voice
- fix login
- we can scroll
- Merge branch 'main' of https://github.com/gr125/treehacks24
- attempt to revive in-website chatbot
- a
- cleaning up
- realigned
- realigned logo
- forgot to import logo on home.js
- fixed typo
- added logo to the second page
- added logo
- added our logo
- Merge branch 'main' of https://github.com/gr125/treehacks24
- Merge branches 'main' and 'main' of
- changes
- Update index.html

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

### treehacks 2/package.json

```
{
  "dependencies": {
    "dotenv": "^16.4.4"
  }
}

```

### treehacks 2/react-login-demo/frontend/package.json

```
{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@clerk/clerk-react": "^4.30.5",
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "axios": "^1.6.7",
    "dotenv": "^16.4.4",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.8.1",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "start-backend": "cd backend && env/bin/flask run --no-debugger",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "proxy": "http://localhost:5000"
}

```

### treehacks 2/react-login-demo/auth-server/app.js

```javascript
const express = require("express")
const bcrypt = require("bcrypt")
var cors = require('cors')
const jwt = require("jsonwebtoken")
var low = require("lowdb");
var FileSync = require("lowdb/adapters/FileSync");
var adapter = new FileSync("./database.json");
var db = low(adapter);

// Initialize Express app
const app = express()

// Define a JWT secret key. This should be isolated by using env variables for security
const jwtSecretKey = "dsfdsfsdfdsvcsvdfgefg"

// Set up CORS and JSON middlewares
app.use(cors())
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Basic home route for the API
app.get("/", (_req, res) => {
    res.send("Auth API.\nPlease use POST /auth & POST /verify for authentication")
})

// The auth endpoint that creates a new user record or logs a user based on an existing record
app.post("/auth", (req, res) => {
    
    const { email, password } = req.body;

    // Look up the user entry in the database
    const user = db.get("users").value().filter(user => email === user.email)

    // If found, compare the hashed passwords and generate the JWT token for the user
    if (user.length === 1) {
        bcrypt.compare(password, user[0].password, function (_err, result) {
            if (!result) {
                return res.status(401).json({ message: "Invalid password" });
            } else {
                let loginData = {
                    email,
                    signInTime: Date.now(),
                };

                const token = jwt.sign(loginData, jwtSecretKey);
                res.status(200).json({ message: "success", token });
            }
        });
    // If no user is found, hash the given password and create a new entry in the auth db with the email and hashed password
    } else if (user.length === 0) {
        bcrypt.hash(password, 10, function (_err, hash) {
            console.log({ email, password: hash })
            db.get("users").push({ email, password: hash }).write()

            let loginData = {
                email,
                signInTime: Date.now(),
            };

            const token = jwt.sign(loginData, jwtSecretKey);
            res.status(200).json({ message: "success", token });
        });

    }


})

// The verify endpoint that checks if a given JWT token is valid
app.post('/verify', (req, res) => {
    const tokenHeaderKey = "jwt-token";
    const authToken = req.headers[tokenHeaderKey];
    try {
      const verified = jwt.verify(authToken, jwtSecretKey);
      if (verified) {
        return res
          .status(200)
          .json({ status: "logged in", message: "success" });
      } else {
        // Access Denied
        return res.status(401).json({ status: "invalid auth", message: "error" });
      }
    } catch (error) {
      // Access Denied
      return res.status(401).json({ status: "invalid auth", message: "error" });
    }

})

// An endpoint to see if there's an existing account for a given email address
app.post('/check-account', (req, res) => {
    const { email } = req.body

    console.log(req.body)

    const user = db.get("users").value().filter(user => email === user.email)

    console.log(user)
    
    res.status(200).json({
        status: user.length === 1 ? "User exists" : "User does not exist", userExists: user.length === 1
    })
})

app.listen(3080)
```

### treehacks 2/react-login-demo/frontend/src/index.js

```javascript
import React from 'react'
import ReactDOM from 'react-dom/client'
import './index.css'
import App from './App'
import reportWebVitals from './reportWebVitals'
import { ClerkProvider } from '@clerk/clerk-react'


const clerkPubKey = "pk_test_cG9wdWxhci1sYW1wcmV5LTQ0LmNsZXJrLmFjY291bnRzLmRldiQ"

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  <ClerkProvider publishableKey={clerkPubKey}>
    <App />
  </ClerkProvider>
)

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals()

```

### treehacks 2/react-login-demo/frontend/src/App.js

```javascript
import React, { useState, useEffect } from 'react';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import Home from './home';
import Login from './login'
import './App.css';

function App() {
  const [loggedIn, setLoggedIn] = useState(false)
  const [email, setEmail] = useState("")

  const handleLogin = (email) => {
    setEmail(email);
    setLoggedIn(true);
  };

//   useEffect(() => {
//     // Fetch the user email and token from local storage
//     const user = JSON.parse(localStorage.getItem("user"))

//     // If the token/email does not exist, mark the user as logged out
//     if (!user || !user.token) {
//       setLoggedIn(false)
//       return
//     }

//     // If the token exists, verify it with the auth server to see if it is valid
//     fetch("http://localhost:3080/verify", {
//             method: "POST",
//             headers: {
//                 'jwt-token': user.token
//               }
//         })
//         .then(r => r.json())
//         .then(r => {
//             setLoggedIn('success' === r.message)
//             setEmail(user.email || "")
//         })
//   }, [])
  return (

    <div>
      {loggedIn ? (
        <Home email={email}/>
      ) : (
        <Login onLogin={handleLogin} />
      )}

    </div>
  );

//   return (
//     <div className="App">
//       <BrowserRouter>
//         <Routes>
//           <Route path="/" element={<Home email={email} loggedIn={loggedIn} setLoggedIn={setLoggedIn}/>} />
//           <Route path="/login" element={<Login setLoggedIn={setLoggedIn} setEmail={setEmail} />} />
//         </Routes>
//       </BrowserRouter>
//     </div>
//   );
}

export default App;

```

### chatbot/test_together_api.py

```python

from openai import OpenAI

user_ehr = open("../postgresql/output.txt","r").read()
TOGETHER_API_KEY = "[API KEY]"

def get_summary(api_key, user_ehr):
    client = OpenAI(api_key=api_key,
        base_url='https://api.together.xyz',
    )

    chat_completion = client.chat.completions.create(
    messages=[
        {
        "role": "system",
        "content": "You are an AI assistant providing the user with a summary of their electronic health record. You are not a physician or a person of authority. You are given this information about the patient: "+user_ehr,
        },
        {
        "role": "user",
        "content": "Create a summary-style report for this patient that describes this patient's current health condition with the aim of educating the patient about their health. Only include information most relevant to the patient. Format the report using bullet points and concise language for increased readability. At the end of the report, include a section of recommendations for actions the patient should take, but emphasize that the patient should communicate with their physician. Title the report 'Current Health Report for [patient]' replacing [patient] with the Patient's first and last name.",
        }
    ],
    model="codellama/CodeLlama-13b-Instruct-hf",
    max_tokens=1024)

    return chat_completion.choices[0].message.content

# append question to chat history prior to calling function
def get_answer(api_key, user_summary, question):
    client = OpenAI(api_key=api_key,
        base_url='https://api.together.xyz',
    )

    if len(chat)==0:
        chat.append(
            {
                "role": "system",
                "content": "You are an AI assistant answering questions the user asks about their health, taking into consideration any questions the user previously asked. You are not a physician or a person of authority. You cannot answer any questions irrelevant to medical health such as payment information, physician information, hospital information, and healthcare providers. You are given this information about the patient: "+user_summary,
            }
        )
        chat.append(
            {
                "role": "user",
                "content": "I am this patient. Please answer this question in detail: "+question,
            }
        )
    else:
        chat.append( 
             {"role":"user", 
              "content": "I am this patient. Please answer this question in detail: "+question}
        )

    chat_completion = client.chat.completions.create(
    messages=chat,
    model="codellama/CodeLlama-13b-Instruct-hf",
    max_tokens=1024)
    chat.append(
        {"role":"assistant", "content":chat_completion.choices[0].message.content}
    )
    return chat_completion.choices[0].message.content

summary = get_summary(api_key=TOGETHER_API_KEY, user_ehr=user_ehr)
print(summary)
chat = []
user_input = input("Ask me about your health conditions, or type 'quit' to end the conversation!\n")
while user_input != "quit":
    bot_response = get_answer(
        api_key=TOGETHER_API_KEY, 
        user_summary=summary, 
        question=user_input,
    )
    print(bot_response)
    user_input = input("Ask me about your health conditions, or type 'quit' to end the conversation!\n")

```

### postgresql/generate_tables.sql

```sql
-- care plans, claims, devices, encounters, imaging studies, immunizations, medications, observations, procedures 
DROP TABLE IF EXISTS patients;

CREATE TABLE patients (
    id VARCHAR(50),
    birthdate DATE,
    deathdate DATE,
    ssn VARCHAR(20),
    drivers VARCHAR(20),
    passport VARCHAR(20),
    prefix VARCHAR(20),
    first VARCHAR(50),
    last VARCHAR(50),
    suffix VARCHAR(20),
    maiden VARCHAR(50),
    marital VARCHAR(20),
    race VARCHAR(20),
    ethnicity VARCHAR(20),
    gender VARCHAR(10),
    birthplace VARCHAR(100),
    address VARCHAR(100),
    city VARCHAR(50),
    state VARCHAR(20),
    county VARCHAR(50),
    fips VARCHAR(20),
    zip VARCHAR(20),
    lat FLOAT,
    lon FLOAT,
    healthcare_expenses FLOAT,
    healthcare_coverage FLOAT,
    income FLOAT
);

DROP TABLE IF EXISTS allergies;

CREATE TABLE allergies (
    "start" TIMESTAMP,
    "stop" TIMESTAMP,
    "patient" VARCHAR(50),
    "encounter" VARCHAR(50),
    "code" VARCHAR(50),
    "system" VARCHAR(100),
    "description" VARCHAR(255),
    "type" VARCHAR(50),
    "category" VARCHAR(50),
    "reaction1" VARCHAR(50),
    "description1" VARCHAR(255),
    "severity1" VARCHAR(50),
    "reaction2" VARCHAR(50),
    "description2" VARCHAR(255),
    "severity2" VARCHAR(50)
);

DROP TABLE IF EXISTS conditions;

CREATE TABLE conditions (
    "start" TIMESTAMP,
    "stop" TIMESTAMP,
    "patient" VARCHAR(50),
    "encounter" VARCHAR(50),
    "code" VARCHAR(50),
    "description" VARCHAR(255)
);

DROP TABLE IF EXISTS observations;

CREATE TABLE observations (
    "date" DATE,
    "patient" VARCHAR(50),
    "encounter" VARCHAR(50),
    "category" VARCHAR(50),
    "code" VARCHAR(50),
    "description" VARCHAR(255),
    "value" VARCHAR(255),
    "units" VARCHAR(50),
    "type" VARCHAR(50)
);

DROP TABLE IF EXISTS account;

CREATE TABLE account (
    "id" VARCHAR(50),
    "email" VARCHAR(50),
    "password" VARCHAR(50) DEFAULT 'password'
);

DROP TABLE IF EXISTS careplans;

-- Create the table
CREATE TABLE careplans (
    "id" VARCHAR(50),
    "start" DATE,
    "stop" DATE,
    "patient" VARCHAR(50),
    "encounter" VARCHAR(50),
    "code" VARCHAR(50),
    "description" VARCHAR(255),
    "reasoncode" VARCHAR(50),
    "reasondescription" VARCHAR(255)
);

-- Copy data from the CSV file
COPY careplans("id","start","stop","patient","encounter","code","description","reasoncode","reasondescription")
FROM '/Users/brendantang/Developer/Treehacks/output/csv/careplans.csv'
DELIMITER ','
CSV HEADER;

COPY observations("date","patient","encounter","category","code","description","value","units","type")
FROM '/Users/brendantang/Developer/Treehacks/output/csv/observations.csv'
DELIMITER ','
CSV HEADER;

COPY conditions("start","stop","patient","encounter","code","description")
FROM '/Users/brendantang/Developer/Treehacks/output/csv/conditions.csv'
DELIMITER ','
CSV HEADER;

COPY allergies("start","stop","patient","encounter","code","system","description","type","category","reaction1","description1","severity1","reaction2","description2","severity2")
FROM '/Users/brendantang/Developer/Treehacks/output/csv/allergies.csv'
DELIMITER ','
CSV HEADER;

COPY patients("id","birthdate","deathdate","ssn","drivers","passport","prefix","first","last","suffix","maiden","marital","race","ethnicity","gender","birthplace","address","city","state","county","fips","zip","lat","lon","healthcare_expenses","healthcare_coverage","income")
FROM '/Users/brendantang/Developer/Treehacks/output/csv/patients.csv'
DELIMITER ','
CSV HEADER;

INSERT INTO account (id, email)
SELECT id, CONCAT(first, last, '@treehacks.edu')
FROM patients;
```

### postgresql/get_patient_info.py

```python
import psycopg2

def get_patient_info(patient_id):
    try:
        # Connect to the database
        conn = psycopg2.connect(
            dbname="ehr",
            user="brendantang",
            host="localhost",
            port="5432"
        )

        # Create a cursor object
        cur = conn.cursor()
        # Fetch data from different tables based on patient ID

        cur.execute("""
            SELECT first, last FROM patients WHERE id = %s;
        """, (patient_id,))
        patient_data = cur.fetchall()

        cur.execute("""
            SELECT start, description, type, category, description1, severity1, description2, severity2 FROM allergies WHERE patient = %s;
        """, (patient_id,))
        allergies_data = cur.fetchall()

        cur.execute("""
            SELECT START,STOP,DESCRIPTION FROM conditions WHERE patient = %s;
        """, (patient_id,))
        conditions_data = cur.fetchall()

        cur.execute("""
            SELECT DATE,CATEGORY,DESCRIPTION,VALUE,UNITS,TYPE FROM observations WHERE patient = %s;
        """, (patient_id,))
        observations_data = cur.fetchall()

        # Fetch careplans information
        cur.execute("""
            SELECT start, stop, description, reasondescription
            FROM careplans 
            WHERE patient = %s 
            AND ((stop IS NULL OR stop >= CURRENT_DATE - INTERVAL '2 years') 
            OR start >= CURRENT_DATE - INTERVAL '4 years');
        """, (patient_id,))
        careplans_data = cur.fetchall()

        # Close cursor and connection
        cur.close()
        conn.close()

        # Return fetched data
        return {
            "patient": patient_data,
            "allergies": allergies_data,
            "conditions": conditions_data,
            "observations": observations_data,
            "careplans": careplans_data
        }

    except psycopg2.Error as e:
        print("Error connecting to PostgreSQL database:", e)

def write_patient_info_to_file(patient_info, file_path):
    try:
        with open(file_path, 'w') as file:
            # Writing patient information
            patient_data = patient_info['patient']
            file.write("Patient Information:\n\n")
            file.write(f"First Name: {patient_data[0][0]}\n")
            file.write(f"Last Name: {patient_data[0][1]}\n\n")
            
            # Writing allergies
            allergies_data = patient_info['allergies']
            file.write("Allergies:\n")
            for allergy in allergies_data:
                file.write(f"Start: {allergy[0]}, Description: {allergy[1]}, Type: {allergy[2]}, Category: {allergy[3]}, Reaction1: {allergy[4]}, Severity1: {allergy[5]}, Reaction2: {allergy[6]}, Severity2: {allergy[7]}\n")
            file.write("\n")
            
            # Writing conditions
            conditions_data = patient_info['conditions']
            file.write("Conditions:\n")
            for condition in conditions_data:
                file.write(f"Start: {condition[0]}, Stop: {condition[1]}, Description: {condition[2]}\n")
            file.write("\n")
            
            # Writing observations
            observations_data = patient_info['observations']
            file.write("Observations:\n")
            for observation in observations_data:
                file.write(f"Date: {observation[0]}, Category: {observation[1]}, Description: {observation[2]}, Value: {observation[3]}, Units: {observation[4]}, Type: {observation[5]}\n")
            file.write("\n")

            # Extracting careplans data
            careplans_data = patient_info['careplans']
            file.write("Careplans:\n")
            for careplan in careplans_data:
                file.write(f"Start: {careplan[0]}, Stop: {careplan[1]}, Description: {careplan[2]}, ReasonDescription: {careplan[3]}\n")
            file.write("\n")
        
        print(f"Patient information has been written to {file_path}")

    except IOError as e:
        print("Error writing to file:", e)

def format_patient_info(patient_info):
    output = ""

    # Extracting patient data
    patient_data = patient_info['patient']
    output += "Patient Information:\n"
    output += f"First Name: {patient_data[0][0]}\n"
    output += f"Last Name: {patient_data[0][1]}\n\n"

    # Extracting allergies data
    allergies_data = patient_info['allergies']
    output += "Allergies:\n"
    for allergy in allergies_data:
        output += f"Start: {allergy[0]}, Description: {allergy[1]}, Type: {allergy[2]}, Category: {allergy[3]}, Reaction1: {allergy[4]}, Severity1: {allergy[5]}, Reaction2: {allergy[6]}, Severity2: {allergy[7]}\n"
    output += "\n"

    # Extracting conditions data
    conditions_data = patient_info['conditions']
    output += "Conditions:\n"
    for condition in conditions_data:
        output += f"Start: {condition[0]}, Stop: {condition[1]}, Description: {condition[2]}\n"
    output += "\n"

    # Extracting observations data
    observations_data = patient_info['observations']
    output += "Observations:\n"
    for observation in observations_data:
        output += f"Date: {observation[0]}, Category: {observation[1]}, Description: {observation[2]}, Value: {observation[3]}, Units: {observation[4]}, Type: {observation[5]}\n"
    output += "\n"

    # Extracting careplans data
    careplans_data = patient_info['careplans']
    output += "Careplans:\n"
    for careplan in careplans_data:
        output += f"Start: {careplan[0]}, Stop: {careplan[1]}, Description: {careplan[2]}, ReasonDescription: {careplan[3]}\n"
    output += "\n"


    return output

# Example usage
patient_id = "5855704c-f73e-5983-0dcd-60049d34bd19"
patient_info = get_patient_info(patient_id)
write_patient_info_to_file(patient_info, 'output.txt')
output = format_patient_info(patient_info)
print(output)

```

### treehacks 2/react-login-demo/frontend/src/setupTests.js

```javascript
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';

```

### treehacks 2/react-login-demo/frontend/src/App.test.js

```javascript
import { render, screen } from '@testing-library/react';
import App from './App';

test('renders learn react link', () => {
  render(<App />);
  const linkElement = screen.getByText(/learn react/i);
  expect(linkElement).toBeInTheDocument();
});

```

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