Skip to content

Project 3: Convergent Design

Concepts: Functional Design

Map [Bin]

  • Purpose: to represent a geographical area and the location of things within it

  • OP: User inputs a geographical location -> all items (bins in our app) associated with that location are shown to the user

  • State:

    • Markers: one Bin → one (Float, Float) Coordinate
  • Actions:

    • addBin(loc: Coordinate, bin: Bin)

        Add a location marker for the given bin to the map at location loc
      
    • removeBin(loc: Coordinate, bin: Bin)

        Assert the given bin exists at the given location
      Remove the given bin’s location marker from the given location
      
    • getBinsByLocation(loc: Coordinate, out: bins: set Bin)

        Return all bins with location markers within a 1 mile radius from loc
      
    • getBinLocation(bin: Bin, out location: Coordinate)

        Assert the given bin exists on the map
      Return the location of the given bin
      
    • updateBinLocation(bin: Bin, location: Coordinate)

        Assert the given bin exists on the map
        Change the given bin’s location marker to be the new given location
      

Bin [Material]

  • Purpose: to represent a waste disposal location and the sort of items it accepts.

  • OP: Bin locations are shown as markers on the map → User selects a single bin marker from the map → User is able to see what type of items the bin accepts for proper waste disposal

  • State:

    • Bins: set Bin
    • Type: Bins -> one “Compost” | “Recycle” | “Trash” | “Donation”
    • AcceptedMaterials: Bins -> set Material
    • CommonlyMisdisposedMaterials: Bins -> set Material
    • Status: Bins -> one “Full” | “Not Full”
    • LastStatusUpdate: Bins -> one Date
  • Actions:

    • addBin(acceptedMaterials, commonlyMisdisposedMaterials: set Material, type: “Compost” | “Recycle” | “Trash” | “Donation”, out: bin: Bin)

        Create and return a new bin with status = “Not Full”, LastStatusUpdate = the current date and the given acceptedMaterials, commonlyMisdisposedMaterials, and type
      
    • deleteBin(bin: Bin)

      Assert the bin exists
      Delete the given bin
      
    • updateBin(bin: Bin, acceptedMaterials, commonlyMisdisposedMaterials: set Materials, type: “Compost” | “Recycle” | “Trash” | “Donation”, status: “Full” | “Not Full”, out: bin: Bin)

      Assert the bin exists
        Update the given bin to have the given acceptedMaterials, commonlyMisdisposedMaterials, type, and status
        Update the bin’s LastStatusUpdate to the current date-time
        Return the updated bin
      
    • updateBinStatus(bin: Bin, newStatus: “Full” | “Not Full”)

        Assert bin exists
        Update status of bin to newStatus and update the bin’s LastStatusUpdate to the current date-time
      
    • getBinType(bin: Bin, out type: “Compost” | “Recycle” | “Trash” | “Donation”)

        Assert the bin exists
        Return the given bin’s type
      
    • getBinInformation(bin: Bin, out: acceptedMaterials: set Materials, commonlyMisdisposedItems: set Materials, type: “Compost” | “Recycle” | “Trash” | “Donation”, status: “Full” | “Not Full”, lastStatusUpdate: one Date)

      Assert the bin exists
      Return the states of the bin
      
    • getBinsByMaterial(material: Material, out: bins: set Bin)

        Return all bins that accept the given material
      
    • getBinsByType(type: “Compost” | “Recycle” | “Trash” | “Donation”, out: bins: set Bin)

      Return all bins with the given type
      
    • getBinsByStatus(status: “Full” | “Not Full”, out: bins: set Bin)

        Return all bins with the given status
      

Material

  • Purpose: to represent what any physical item can be made of

  • OP: When users search for bins to dispose of their item, only bins that accept the material the item is made of will be shown.

  • State:

    • Materials: set Material
    • Image, Description, Name, RIC: materials → one String
    • Type: materials → “Recyclable” | “Compostable” | “Solid Waste” | “Donatable”
  • Actions:

    • getMaterialsByName(name: String, out materials: set Material)

        Return all materials with the given name
      
    • getMaterialsByRIC(RIC: String, out materials: set Material)

        Return all materials with the given RIC
      
    • updateMaterial(material: Material, image: String, description: String, name: String, RIC: String, out material: Material)

        Assert material exists
        Update the image, description, name, and RIC of the given material to the new values
        Return the updated material
      
    • removeMaterial(material: Material)

        Assert material exists
        Delete the material
      
    • createMaterial(image, description, name, RIC: String, out material: Material)

        Assert no material with the given name or RIC exists
        Create and return a new material with the given image, description, name, and RIC
      
    • getMaterialType(material: Material, out type: “Recyclable” | “Compostable” | “Solid Waste” | “Donatable”)

        Assert the material exists
        Return the type of the material
      

Score [User]

  • Purpose: Signify how well something is doing

  • OP: User starts with having properly disposed of 0 items (i.e. score 0) → user self-reports that they have properly disposed of something to increase their score → users can earn badges for achieving certain scores → their scores will be personally displayed in their profile

  • State:

    • scores: set Score
    • value: scores -> one Int
    • name: scores -> one String
    • userScores: scores -> one User
  • Actions:

    • setScore(user: User, name: String, newScore: Int, out: score: Int)

        If no score with the given name exists:
            create a new score with name name set to newScore
        Else:
            Update the score with name name to have value newScore
            Return the score’s updated value
      
    • getScore(user: User, name: String, out: score: Int)

        Assert score with name name exists
        Return the score’s current value
      

Achievement [User, Score, Community]

  • Purpose: Show a goal has been reached

  • OP: Users earn different tiered achievements based on their score for how many items they have properly disposed of. Members in a community can earn achievements when the community earns an achievement.

  • State:

    • Achievements: set Achievement
    • Requirements: achievements -> set Score
    • Name: achievements -> one String
    • Type: achievements -> “User” | “Community”
    • UserAchievements: achievements -> set User
    • CommunityAchievements: achievements -> set Community
  • Actions:

    • getAllAchievements(out: achievements: set Achievement)

        Return all achievements
      
    • getAchievementRequirements(achievement: Achievement, out: requirements: set Score)

        Assert achievement exists
        Return the set of Scores needed to earn the achievement
      
    • createAchievement(name: String, requirements: set Score, type: “User” | “Community”, out: achievement: Achievement)

        Assert an achievement with the given name, type, and requirements does not already exist
        Return an Achievement with the given name, type, and requirements
      
    • deleteAchievement(achievement: Achievement)

        Assert the achievement exists
        Delete the achievement and remove it from all users’ or communities’ achievements
      
    • addUserAchievements(user: User, achievements: Achievement, out: newAchievements: set Achievement)

        For each achievement in achievements:
            Assert achievement type is “User”
            Assert user does not already have achievement
            Add the user to the achievement’s set of users who have earned it
        Return all new achievements added
      
    • removeUserAchievement(user: User, achievement: Achievement)

        Assert user has the achievement
        Remove the achievement from the user’s set of achievements
      
    • getUserAchievements(user: User, out: achievements: set Achievement)

        Assert user exists
        Return all the achievements the user currently has
      
    • getNewUserAchievementsEarned(user: User, out: achievements: set Achievement)

        Assert user exists
        Get all “User” achievements and their requirements
        Get the scores and achievements of the user
        Return all achievements that the user meets the requirements for but does not already have
      
    • addCommunityAchievements(community: Community, achievements: Achievement, out: newAchievements: set Achievement)

        For each achievement in achievements:
            Assert achievement type is “Community”
            Assert community does not already have achievement
            Add the community to the achievement’s set of communities that have achieved it
        Return all new achievements added
      
    • removeCommunityAchievement(community: Community, achievement: Achievement)

        Assert community has the achievement
        Remove the achievement from the community’s set of achievements
      
    • getCommunityAchievements(community: Community, out: achievements: set Achievement)

        Assert community exists
        Return all the achievements the community currently has
      
    • getNewCommunityAchievementsEarned(community: Community, out: achievements: set Achievement)

        Assert community exists
            Get all “Community” achievements and their requirements
        Get the scores (sum of all member scores) and achievements of the community
        Return all achievements that the community meets the requirements for but does not already have
      

Fact

  • Purpose: Represents a statement or piece of information that can be objectively verified as true.

  • OP: On the landing page, the user views a random fact related to sustainable waste management. The fact changes to a new random fact each session.

  • State:

    • facts: set Fact
    • fact: facts -> one String
  • Actions:

    • createFact(statement: String, out fact: Fact)

        Assert a Fact with the given statement does not already exist
        Return a Fact with the given statement
      
    • deleteFact(fact: Fact)

        Assert the given Fact exists
        Delete the given Fact
      
    • editFact(fact: Fact, statement: String, out editedFact: Fact)

        Assert the given Fact exists
        Update the fact to the new statement
        Return the updated fact
      

Community [User]

  • Purpose: Group users together based on a commonality

  • OP: User joins a community -> user properly disposes of items and earns scores for their community -> when a community earns an achievement, all users in that community will also earn the achievement

  • State:

    • Communities: set Community
    • Name: communities -> one String
    • Members: communities -> set User
  • Actions:

    • createCommunity(name: String, out: community: Community)

        Assert community with name does not exist
        Create and return new community with name name
      
    • deleteCommunity(name: String)

        Assert community with name exists
        Delete community with name name
      
    • getAllMembersInCommunity(community: String, out: members; set User)

        Assert community with name exists
        Return all users in the given community
      
    • addUserToCommunity(user: User, communityName: String)

        Assert community with name exists and user is not already in the community
        Add user to the community
      
    • removeUserFromCommunity(user: User, communityName: String)

        Assert community with name exists and user is in the community
        Remove user from the community
      
    • getCommunitiesByUser(user: User, out: communities: set Communities)

        Assert user exists
        Return all communities user is a member of
      

User

  • Purpose: Authenticate users

  • OP: User registers with a username and password → they can later authenticate with same username and password combo.

  • State:

    • registered: set User
    • username, password: registered -> one String
  • Actions:

    • register (username, password: String, out u: User)

      	assert username, password not in registered
      add new User with username, password to registered
      return User
      
    • authenticate (username, password: String, out u: User)

      	assert username, password combo in registered
      	return User
      

AccessList [User]

  • Purpose: restrict actions on the app to a subset of users

  • OP: Users all have an access level -> “admin” users can do everything -> “organization” users can only update bins -> all users can view the map and update the bin status

  • State:

    • Users: set User
    • AccessLevel: users -> “Admin” | “Organization” | “None”
  • Actions:

    • getUserAccess (user: User, out: access: “Admin” | “Organization” | “None”)

        Assert user exists
        Return user’s access level
      
    • updateUserAccess (admin, user: User, access: “Admin” | “Organization” | “None”)

        Assert admin has Admin access
        Assert user exists
        Update user’s access level accordingly
      

UserSettings [User]

  • Purpose: store a user’s preferences

  • OP: User sets a default location -> user opens map which initially loads to their default location

  • State:

    • Users: set User
    • defaultLocation: users -> lone Coordinate
  • Actions:

    • setDefaultLocation(user: User, loc: Coordinate)

        Set the user’s default location to loc such that when the user opens the map, they initially see loc and it’s surrounding area
      
    • getDefaultLocation(user: User, out: loc: Coordinate)

      Return the user’s default location
      

Session [User]

  • Purpose: Authenticate users for extended period

  • OP: User authenticates with the password and username combo they registered with → user stays logged in until they log out again → can perform other actions on the app as long as they are logged in

  • State:

    • active: Session → one User
  • Actions:

    • start (user: User, out: s: Session)

        assert no active session
        return new Session whose active user is User
      
    • end (session: Session)

        assert active session
        end the user session (i.e. remove the active: session → user relation for the given session)
      
    • getUser (session: Session, out: u: User)

        assert active session
        return the User that session is mapped to by active
      

Synchronizations

App: WasteWise
include User
include Session [User.User]
include AccessList [User.User]
include UserSettings [User.User]
include Achievement [User.User, Score.Score, Community.Community]
include Score [User.User]
include Community [User.User]
include Map [Bin.Bin]
include Bin [Material.Material]
include Material
include Fact

sync register (username, password: String, out user: User)
   User.register(username, password, user)
   Score.setScore(user, ”Compost”, 0, compostScore)
   Score.setScore(user, “Recycle”, 0, recylceScore)
   Score.setScore(user, “Trash”, 0, trashScore)
   Score.setScore(user, “Donation”, 0, donationScore)

sync login (username, password: String, out user: User, out session: Session)
   when User.authenticate(username, password, user)
   Session.start(user, session)

sync logout (user: User, session: Session)
   when Session.end(session)

sync authenticate (session: Session, user: User)
   Session.getUser(session, user)

sync createBin (user: User, acceptedMaterials: set Material, commonlyMisdisposedMaterials: set Material, type:“Compost” | “Recycle” | “Trash” | “Donation”, location: Coordinate, out bin: Bin)
   AccessList.getUserAccess(user, access)
   Bin.addBin(acceptedMaterials, commonlyMisdisposedMaterials, type, bin)
   Map.addBin(location, bin)

sync deleteBin (user: User, bin: Bin)
   AccessList.getUserAccess(user, access)
   Map.getBinLocation(bin, location)
   Map.removeBin(location, bin)
   Bin.deleteBin(bin)

sync updateBin (user: User, bin: Bin, acceptedMaterials, commonlyMisdisposedMaterials: set Materials, type: “Compost” | “Recycle” | “Trash” | “Donation”, status: “Full” | “Not Full”, location: Coordinate, out bin: Bin)
   AccessList.getUserAccess(user, access)
   Bin.updateBin(bin, acceptedMaterials, commonlyMisdisposedMaterials, type, status, bin)
   Map.updateBinLocation(bin, location)

sync updateBinStatus(session: Session, bin: Bin, newStatus: “Full” | “Not Full”)
   Session.getUser(session, user)
   Bin.updateBinStatus(bin, newStatus)

sync getBinsByMaterial(material: Material, out bins: set Bin)
   Bin.getBinsByMaterial(material, bins)

sync getBinsByType(type: “Compost” | “Recycle” | “Trash” | “Donation”, out bins: set Bin)
   Bin.getBinsByType(type, bins)

sync getBinsByStatus(status: “Full” | “Not Full”, out bins: set Bin)
   Bin.getBinsByStatus(status, bins)

sync getBinsByLocation(location: Coordinate, out bins: set Bin)
   Map.getBinsByLocation(location, bins)

sync getBinInformation(bin: Bin, out: acceptedMaterials: set Materials, commonlyMisdisposedItems: set Materials, type: “Compost” | “Recycle” | “Trash” | “Donation”, status: “Full” | “Not Full”, lastStatusUpdate: one Date)
   Bin.getBinInformation(bin, acceptedMaterials, commonlyMisdisposedItems, type, status, lastStatusUpdate)

sync createAchievement(user: User, name: String, requirements: set Score, type: “User” | “Community”, out: achievement: Achievement)
   AccessList.getUserAccess(user, access)
   Achievement.createAchievement(name, requirements, type, achievement)

sync deleteAchievement(user: User, achievement: Achievement)
   AccessList.getUserAccess(user, access)
   Achievement.deleteAchievement(achievement)

sync removeUserAchievement(user: User, user2: User, achievement: Achievement)
   AccessList.getUserAccess(user, access)
   Achievement.removeUserAchievement(user2, achievement)

sync removeCommunityAchievement(user: User, community: Community, achievement: Achievement)
   AccessList.getUserAccess(user, access)
   Achievement.removeCommunityAchievement(community, achievement)

sync recycleAtBin(session: Session, bin: Bin, out: achievementsEarned: set Achievement)
   Session.getUser(session, user)
   Bin.getBinType(bin, type)
   Score.getScore(user, type, score)
   Score.setScore(user, type, score + 1, newScore)
   Achievement.getNewUserAchievementsEarned(user, newAchievements)
   Achievement.addUserAchievements(user, newAchievements, userAchievementsEarned)
   Community.getCommunitiesByUser(user, communities)
   Achievement.getNewCommunityAchievementsEarned(community, communityAchievements)
   Achievement.addCommunityAchievements(community, communityAchievements, communityAchievementsEarned)

sync recycleMaterial(session: Session, material: Material)
   Session.getUser(session, user)
   Material.getMaterialType(material, type)
   Score.getScore(user, type, score)
   Score.setScore(user, type, score + 1, newScore)
   Achievement.getNewUserAchievementsEarned(user, newAchievements)
   Achievement.addUserAchievements(user, newAchievements, userAchievementsEarned)
   Community.getCommunitiesByUser(user, communities)
   Achievement.getNewCommunityAchievementsEarned(community, communityAchievements)
   Achievement.addCommunityAchievements(community, communityAchievements, communityAchievementsEarned)

sync createCommunity(user: User, name: String, out: community: Community)
   AccessList.getUserAccess(user, access)
   Community.createCommunity(name, community)

sync deleteCommunity(user: User, name: String, out: community: Community)
   AccessList.getUserAccess(user, access)
   Community.deleteCommunity(name)

sync getAllMembersInCommunity(community: String, out: members; set User)
   Community.getAllMembersInCommunity(community, members)

sync addUserToCommunity(session: Session, communityName: String)
   Session.getUser(session, user)
   Community.addUserToCommunity(user, communityName)

sync removeUserFromCommunity(session: Session, user2: User, communityName: String)
   Session.getUser(session, user)

Dependency Diagram

Dependency Diagram

Wireframes

Here is a link to our Figma wireframes: https://www.figma.com/file/SY8pwlYwSjEkIm32CZoSz5/[6.170]-Final-Project?type=design&node-id=0%3A1&mode=design&t=Or1kUAKhAPqymVZK-1.

The prototype can be viewed in the window below:

From the site's landing page, users can immediately begin searching for recycling information on certain items (and even view a fun fact!). Landing Page

The search page allows users to search our database by name and query. Search Page

After clicking on a database entry, users can find more information on the material that they have found. Material Page

The map will have markers showing the locations of neaby disposal bins. Clicking on a marker will open up a panel with more information on what can be recycled in said bin along with its last reported capacity. Map

From their dashboard, users can view their recycling metrics alongside any badges that they have earned for their recycling habits. Dashboard

Heuristic Evaluation

Usability Criteria

Learnability: Since learning to use a new application for disposing waste may seem like a nuisance for many users, we made our app’s most essential tool, the search bar, the easiest to find. Having the largest font on the home page, our search bar requires almost no effort to locate. Using the search bar immediately directs the user to a search page that only contains the search bar, other methods of searching, and the search results. With one more click, a user can find more information about a materia/item or start locating a disposal bin, each with their own dedicated pages. We use text to clearly indicate to the user what actions can be taken. We decided to have an expandable navigation bar rather than one with all the options constantly present at the top of the page to prevent cluttering as much as possible. Since most users these days are aware of expandable navigation bars, we think this is a good tradeoff to take. By having the most powerful tool readily available and having clear guides towards next steps, we believe our app’s interface can be rapidly and easily learned.

Efficiency: We believe our interface can be used very quickly and efficiently for reasons similar to why we believe it is very learnable, and to make it even more efficient, our app includes suggested and related content/functionalities based on users’ actions. Firstly, as mentioned before, the essential search bar is readily available, and the flow to finding key information, e.g. bin locations, is very short, with user guidance at each step. Our home page displays commonly misrecycled items and commonly searched items, anticipating our users’ needs, possibly saving them from typing and just clicking once to search. Similarly, when looking for more information on an item, related items are displayed, possibly saving them from having to constantly return back to the search results. We hope to even include a list of items recently searched by the user themselves, perhaps on the home page, in case a user needs to remember how to dispose of an item again.

Physical Heuristics

Situational Context: All of our pages (except the leaderboard) do not display their names. Instead, our interface conveys to the user where they are on our site based on the functionalities displayed. For example, the page with the map does not have a title, but the only component on it is the map and the map’s functionalities. We think that this helps the user quickly depict what the main purpose of the page is, and therefore it might not need a name for efficient navigation, while keeping the text at a minimum. On our search page, the search icon and bar serve as the “page name”, since they give a clear idea on what the page is about. Despite this, we will certainly consider displaying page names if it does speed up navigation since we want as much as possible for the user to not feel that our app is too inconvenient for sustainability. On pages displaying information about a certain material/item, we can add leftward arrows that bring back the user to the search results page so that they do not have to expand the navigation bar and search their material again.

Fitt’s Law: The essential elements on our pages are all very large, making them easily reachable by users. The search bar on the home page and the search page is huge and is located at the top center of those pages. The user needs only the slightest bit of accuracy to click it, and they can always count on finding it at the top of the page. For the search results, we currently have users click the name of the item to navigate to its information page, but it is probably better to allow the entire block containing the image and option to see disposal locations to be clickable and navigate the user to the corresponding page. For the navigation bar, making it vertically longer, perhaps taking up the whole page, might be a better option, as well as using borders or different colors to clearly mark the area of each tile and to which destination it corresponds to.

Linguistic Level

Consistency: For the most part, our interface uses icons and names consistent with users’ expectations of websites. In the navigation bar, all the destinations have icons and names that are prevalent on the web. To show users can go further into a particular list or item, we have the familiar SEE [X] followed by an arrow, such as under the “Commonly Misrecycled Items” section on the homepage, or on the search results page. We use the reuse, reduce, recycle sign to show that an item is recyclable, staying consistent with the field of waste disposal. There is some room for improvement when it comes to the button that says “Log Recycle” present on an item’s information page and on the map. Firstly, not all items can be recycled, so we need to either use a more general word, perhaps like “Disposal”, or adjust for each type of item. Secondly, recycle is commonly used as a verb, so “Log Recycle” can be a little difficult to comprehend. Lastly, adding an icon, perhaps one that implies writing something down on a list, can make it more clear to the user that clicking the button will allow them to add their disposal of the item to their personal log (if they are logged in).

Information Scent: Our interface uses icons, text, and direction to guide our user towards the information they want to look up. On the homepage, our search bar lacks a search icon but instead leaves a sentence to be completed by the user, showing example search prompts to imply to the user to fill in the question and begin their search. We describe an action in text and include a rightward arrow next to it in the search page and home page to signify that these actions propel the user forward into their search. We believe our interface does a great job with concise naming of actions and mapping them to pages/effects that are expected. Like mentioned above, we can improve on how we present the “Log Recycle” button to be informative and clear to the user about what that action does.

Visual Design Study

Color Design Study

Color Design Study

Typography Design Study

Typography Design Study

Project Plan

Our concepts are listed below in order of dependency and importance to the core functionality of our application:

  1. Session
    • Backend implementation: A direct copy/paste from the starter code—no additions need to be made. (login/logout/register syncs) - LJ (EOD Nov 27th)
    • Frontend implementation - Diego (Nov 30)
      • Navbar/menu
      • login/register form
  2. User
    • Backend implementation: After copying/pasting from the starter code, incorporate “permissions” (admin, org, none) into the state of User - LJ (EOD Nov 27th)
    • Frontend implementation - Grace (Nov 30)
      • Settings Page (updating username/password)
      • Dashboard (only name & title)
  3. Material - Dana + LJ
    • Backend implementation - (Nov 28)
    • Populate with realistic data - (Nov 28)
    • Frontend implementation - (Nov 30)
      • Material Page (Disposal locations & log recycle button do not have to be working yet)
      • Search Page
  4. Fact - Grace + Diego
    • Backend implementation - Grace (Nov 28)
    • Populate with realistic data - Grace (Nov 28)
    • Frontend implementation - Diego (Nov 30)
      • Fact component on landing page
  5. Bin - LJ (Dec 4)
    • Backend implementation
    • Populate with realistic data (must be done after 3b)
    • Frontend implementation (bin component on map page)
  6. Map
    • Backend implementation - Dana (Dec 3)
    • Populate with realistic data (must be done after 4b) - Dana (Dec 3)
    • Frontend implementation (finish map page) - LJ (Dec 7)
  7. Score - Diego
    • Backend implementation (Dec 3)
    • Frontend implementation (Dec 7)
      • User metrics on Dashboard
      • Global metrics on landing page
  8. Achievement
    • Backend implementation - Grace (Dec 4)
    • Populate with realistic achievements - Grace (Dec 4)
    • Frontend implementation - Diego (Dec 7)
  9. Community - Dana (Dec 7)
    • Backend implementation
    • Populate with realistic data
    • Frontend implementation
      • Chips on dashboard page
      • Syncs with Map
  10. AccessList - Diego (Dec 7)
    • Backend implementation
    • Frontend implementation
  11. UserSettings - Dana (Dec 7)
    • Backend Implementation
    • Frontend Implementation
  12. User Testing - Everyone
    • Find and plan interviews - Everyone (Dec 9)
    • Write up - Grace and Diego (Dec 10)
      • Review and Revise - Everyone (Dec 12)
    • Final Review - Everyone (Dec 13)

Our goal is to have the first four concepts on this list (User, Session, Material, and Fact) completed end-to-end by the alpha release. Should certain concepts take more time than expected, or we otherwise find ourselves low on time, we’ll limit the scope of our application by excluding the concepts listed later on the list. Specifically, we will first start by removing the AccessList and UserSettings concepts, then the Community concept and all features that depend on it such as community type achievements. If after redistributing tasks, we find that we still do not have enough time, we will forgo the Achievement concept and put more emphasis into the score concept to still gamify our app and promote its use amongst users.