Skip to content

Project Milestone 3

Isaac edited this page Nov 5, 2024 · 50 revisions

Architectural Tactic for Availability

Work through the checklist to decide how to address your system's quality attribute of Availability. Select appropriate architectural tactics to ensure availability based on your decisions. Your architecture should use at least five architectural availability tactics. Implement the code for these five architectural tactics in your project. On your Wiki, create a section "Architecture Tactics - Availability" where you (1) include your checklist or set of questions/criteria to assess and evaluate architecture tactic, (2) the architecture tactic you selected, (3) how this tactic is manifested in your design, and (4) how you plan to test whether your quality attribute objective will be met.

image

Exception Handling

each fetch is checked

Graceful Degradation

login and enter tell the user gracefully it didn't work

Sanity Checking

https://react-bootstrap.netlify.app/docs/forms/form-control/

Design Patterns

For your project, identify and plan at least five design patterns in your design and system. It should be a pattern that you implement. On your Wiki, create a section, "Design Patterns," where you describe each design pattern in general and how they manifest in your design and system. Implement the code for these five design patterns in your project.

LIAM PUT COPILOT HERE:

1. Decorator Pattern

The Decorator pattern allows behavior to be added to individual objects, dynamically, without affecting the behavior of other objects from the same class. In your project, this pattern is evident in the use of decorators in FastAPI.

Example in FastAPI:

  • Route Decorators: The @router.get, @router.post, @router.put, and @router.delete decorators in triage_routes.py add routing behavior to the functions they decorate.
@router.get("/tickets", response_model=List[VTTicket])
async def get_all_tickets():
    return await get_tickets()
  • Middleware Decorators: The @app.middleware decorator can be used to add middleware to the FastAPI application.
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

2. Observer Pattern

The Observer pattern is used to allow an object to notify other objects about changes in its state. In your project, this pattern is evident in the use of React's useEffect hook, which allows components to react to changes in state or props.

Example in React:

  • useEffect Hook: The useEffect hook in NurseWaiting.js observes changes in the component's state and performs side effects like data fetching.
useEffect(() => {
  const fetchTickets = async () => {
    try {
      const response = await fetch('/api/triage-tickets');
      const data = await response.json();
      setTickets(data);
    } catch (error) {
      console.error('Error fetching tickets:', error);
    } finally {
      setLoading(false);
    }
  };

  fetchTickets();
}, []);

3. Factory Pattern

The Factory pattern is used to create objects without specifying the exact class of object that will be created. In your project, this pattern is evident in the creation of VTTicket instances from the data fetched from the database.

Example in FastAPI:

  • Creating VTTicket Instances: The VTTicket model's constructor acts as a factory method to create instances of the model from the data returned by the database.
async def get_tickets() -> List[VTTicket]:
    try:
        tickets = list(tickets_collection.find({}, {'_id': 0}))  # Exclude the MongoDB _id field
        return [VTTicket(**ticket) for ticket in tickets]
    except Exception as e:
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e))

4. Model-View-Controller (MVC) Pattern

The MVC pattern separates an application into three main components: Model, View, and Controller. This separation helps in organizing the code and promoting reusability and maintainability.

Example in Your Project:

  • Model: The VTTicket model in VirtualTriage.py defines the structure of the data.
class VTTicket(BaseModel):
    ticketID: int
    userID: str
    ED: str
    consent: bool
    timestamp: str
    generalSymptoms: GeneralSymptoms
    respiratorySymptoms: RespiratorySymptoms
    gastrointestinalSymptoms: GastrointestinalSymptoms
    neurologicalSymptoms: NeurologicalSymptoms
    musculoskeletalSymptoms: MusculoskeletalSymptoms
    cardiovascularSymptoms: CardiovascularSymptoms
    skinSymptoms: SkinSymptoms
    psychologicalSymptoms: PsychologicalSymptoms
    substanceHabits: SubstanceHabits
    allergies: List[str]
    medications: List[str]
    durationOfSymptoms: str
    listAllergies: List[str]
    pastMedicalConditions: List[str]
  • View: The NurseWaiting.js React component is responsible for rendering the user interface.
const NurseWaiting = () => {
  const [tickets, setTickets] = useState([]);
  const [loading, setLoading] = useState(true);
  const [selectedTicket, setSelectedTicket] = useState(null);

  useEffect(() => {
    const fetchTickets = async () => {
      try {
        const response = await fetch('/api/triage-tickets');
        const data = await response.json();
        setTickets(data);
      } catch (error) {
        console.error('Error fetching tickets:', error);
      } finally {
        setLoading(false);
      }
    };

    fetchTickets();
  }, []);

  if (loading) {
    return <div>Loading...</div>;
  }

  if (selectedTicket) {
    return (
      <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', marginTop: '20px' }}>
        <h1>Ticket Details</h1>
        <div style={{
          border: '1px solid #ccc',
          padding: '20px',
          borderRadius: '5px',
          backgroundColor: '#f9f9f9',
          width: '80%',
          textAlign: 'center',
          transition: 'transform 0.2s, background-color 0.2s',
        }}>
          <strong>User ID:</strong> {selectedTicket.userID || 'N/A'}
          <div><strong>Timestamp:</strong> {selectedTicket.timestamp}</div>
          <div><strong>Allergies:</strong> {selectedTicket.listAllergies?.join(', ') || 'None'}</div>
          <div><strong>Duration:</strong> {selectedTicket.durationOfSymptoms || 'N/A'}</div>
          
          <h3>Symptoms:</h3>
          <div>
            {Object.entries(selectedTicket).map(([key, value]) => {
              if (typeof value === 'object' && value !== null) {
                return (
                  <div key={key}>
                    <strong>{key}:</strong>
                    <ul>
                      {Object.entries(value).map(([symptom, hasSymptom]) => (
                        <li key={symptom}>{symptom}: {hasSymptom ? 'Yes' : 'No'}</li>
                      ))}
                    </ul>
                  </div>
                );
              }
              return null;
            })}
          </div>

          <button onClick={() => setSelectedTicket(null)} style={{ marginTop: '20px' }}>Back</button>
        </div>
      </div>
    );
  }

  return (
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', marginTop: '20px' }}>
      <h1 style={{ marginBottom: '20px' }}>Incoming Triage Tickets</h1>
      <div style={{ width: '80%', display: 'flex', flexDirection: 'column', gap: '10px' }}>
        {tickets.map(ticket => (
          <div key={ticket.ticketID} style={{
            border: '1px solid #ccc',
            padding: '10px',
            borderRadius: '5px',
            backgroundColor: '#f9f9f9',
            transition: 'transform 0.2s',
            cursor: 'pointer'
          }}
            onMouseEnter={(e) => {
              e.currentTarget.style.transform = 'scale(1.05)';
              e.currentTarget.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.1)';
            }}
            onMouseLeave={(e) => {
              e.currentTarget.style.transform = 'scale(1)';
              e.currentTarget.style.boxShadow = 'none';
            }}
            onClick={() => setSelectedTicket(ticket)}
          >
            <strong>User ID:</strong> {ticket.userID}
            <div><strong>Timestamp:</strong> {ticket.timestamp}</div>
            <div><strong>Allergies:</strong> {ticket.listAllergies?.join(', ') || 'None'}</div>
            <div><strong>Duration:</strong> {ticket.durationOfSymptoms || 'N/A'}</div>
          </div>
        ))}
      </div>
    </div>
  );
};

export default NurseWaiting;
  • Controller: The FastAPI routes in triage_routes.py handle the HTTP requests and interact with the data models.
from fastapi import APIRouter, Depends
from models.VirtualTriage import VTTicket
from services.triage_service import get_tickets, create_ticket, update_ticket, delete_ticket
from typing import List

router = APIRouter()

@router.get("/tickets", response_model=List[VTTicket])
async def get_all_tickets():
    return await get_tickets()

@router.post("/tickets", response_model=VTTicket)
async def create_new_ticket(ticket: VTTicket):
    return await create_ticket(ticket)

@router.put("/tickets/{ticket_id}", response_model=VTTicket)
async def update_existing_ticket(ticket_id: int, ticket: VTTicket):
    return await update_ticket(ticket_id, ticket)

@router.delete("/tickets/{ticket_id}", response_model=dict)
async def delete_existing_ticket(ticket_id: int):
    return await delete_ticket(ticket_id)

ERICH PUT STATE PATTERN HERE:

Design Diagrams and System Description

Update all the previous UML Diagrams and the System Description according to feasibility and changed requirements. This should be in detail as to why they were changed and not feasible.

Contributions

Summarize the contributions made by each team member. (Point out the sections/parts each group member was "most responsible" for.)

Clone this wiki locally