CSC/ECE 517 Fall 2023 - E2360. View for Results of Bidding

From Expertiza_Wiki
Jump to navigation Jump to search

Expertiza

Expertiza is an open source project based on Ruby on Rails framework. Expertiza allows the instructor to create new assignments and customize new or existing assignments. It also allows the instructor to create a list of topics the students can sign up for. Students can form teams in Expertiza to work on various projects and assignments. Students can also peer review other students' submissions. Expertiza supports submission across various document types, including URLs and wiki pages.

Background

When topics are opened up for bidding, students can see how “hot” each topic is by the color it has on their topic list. However, instructors have no way to view the bidding process except by impersonating students. Furthermore, when the bidding assignment algorithm is run, there is no way to verify that it did in fact assign teams to topics they had chosen.


Previous Work

CSC/ECE_517_Spring_2022_-_E2245:_View_for_results_of_bidding

Accomplishments

This project added a "View Bidding Details" when the instructor enables the "bidding for topics" feature. By clicking it, it redirects us to a new page, where shows the following details of bidding:

  • Topic Name
  • Bidding Teams
  • Bidding Order
  • The number of bidding a topic gets

Also, for each topic, the team that wins the bidding will be highlighted with a yellow background color so that the instructor can easily find out which team each topic is assigned to.

The button leads to a page that contains bidding information for the assignment. It displays the number of #1, #2, and #3 bids on a specific topic, the teams that bid and priority of their bid, and the name of the team that got assigned the topic is highlighted.

Files Involved:

The files to be worked upon are:

  • ./app/controllers/lottering_controller.rb
  • ./app/views/lottery/bidding_details.ntml.erb
  • ./app/assignments/edit/_topics.html.erb
  • ./spec/controllers/lottery_controller.rb

Team Members

  • Richard Li rli14@ncsu.edu
  • Shreshth Malik smalik4@ncsu.edu
  • Shuai Chen schen76@ncsu.edu


Implemented Code

1. Lottery Controller

File: ./app/controllers/lottery_controller.rb

Method: "bidding_details"

Functionality:

(1) Assignment Retrieval:

  • Retrieves the assignment based on the provided id from the params.

(2) Topic Fetching:

  • Gathers all the sign-up topics associated with the retrieved assignment.

(3) Initialization of Data Structures:

  • Initializes two hash data structures:
  1. @bids_by_topic: To store bids by topic.
  2. @assigned_teams_by_topic: To store teams assigned to each topic.

(4) Data Aggregation:

Iterates through each topic and performs the following actions:

(i) Bids Gathering:

  • Fetches all bids for each topic.
  • Bids are stored in @bids_by_topic, mapped by the topic.id. Each bid includes the team and its priority.

(ii) Assigned Teams Gathering:

  • Retrieves teams that are assigned to a topic and are not waitlisted.
  • The results are stored in @assigned_teams_by_topic, indexed by topic.id.

(5) Priority Counts:

  • For each topic, the method calculates the number of bids at each priority level (1 to 3).
  • It dynamically initializes and updates three instance variables: @count1, @count2, and @count3.
  • Each of these variables is a hash that maps topic IDs to the count of bids at the respective priority.
def bidding_details
    @assignment = Assignment.find(params[:id])
    # Fetch all topics for the assignment
    @topics = @assignment.sign_up_topics
    # Fetch all bids for these topics
    @bids_by_topic = {}
    @assigned_teams_by_topic = {} # This will store the assigned teams for each topic
    @topics.each do |topic|
      # Assuming bids are stored with a topic_id, and each bid has a team associated with it
      @bids_by_topic[topic.id] = Bid.where(topic_id: topic.id).map { |bid| { team: bid.team, priority: bid.priority } }
      # Fetch teams that are not waitlisted for this topic
      @assigned_teams_by_topic[topic.id] = SignedUpTeam.where(topic_id: topic.id, is_waitlisted: false).map(&:team)
      # Dynamically initializing and updating @count1, @count2, and @count3
      (1..3).each do |priority|
        instance_variable_set("@count#{priority}", Hash.new(0)) unless instance_variable_defined?("@count#{priority}")
        instance_variable_get("@count#{priority}")[topic.id] = @bids_by_topic[topic.id].count { |bid| bid[:priority] == priority }
      end
    end
  end

2. Bidding Details View

File: ./app/views/lottery/bidding_details.html.erb

Added a button and corresponding JavaScript which toggles its visibility based on “Enable bidding for topics?” checkbox.

Components:

1. Custom CSS Style:

  • A style block is defined to style elements with the assigned-team class. Teams assigned to a topic will have a yellow background and black text.

2. Bidding Details Table:

  • A table is created with classes table, table-bordered, and table-hover for styling.
  • The header (<thead>) section of the table defines five columns: "Topic Name", "Bidding Teams", and three columns for bid counts ("#1 bids", "#2 bids", "#3 bids").

3. Dynamic Table Rows:

  • The <tbody> section uses ERB to iterate over each topic in the @topics array.
  • Each topic creates a table row () with the following data:
    • Topic Name: Displayed using <%= topic.topic_name %>.
    • Bidding Teams: A list of teams bidding on the topic. For each bid associated with the topic:
      • The team's name and priority number are displayed.
      • If the team is assigned to the topic, it is styled with the assigned-team class.
    • Bid Counts: Three columns display the number of #1, #2, and #3 bids for each topic. If there are no bids, it displays "No bids yet".

4. Navigation Link:

<a href="javascript:history.back()">Back</a>: Provides a link to go back to the previous page in the browser history.

<h3>Bidding Details for <%= @assignment.name %></h3>

<style>
.assigned-team {
  background-color: yellow; 
  color: black;             
}
</style>

<table class="table table-bordered table-hover">
  <thead>
    <tr>
      <th>Topic Name</th>
      <th>Bidding Teams</th>
      <th>#1 bids</th>
      <th>#2 bids</th>
      <th>#3 bids</th>
    </tr>
  </thead>
  <tbody>
    <% @topics.each do |topic| %>
      <tr>
        <td><%= topic.topic_name %></td>
        <td>
          <% @bids_by_topic[topic.id].each do |bid_info| %>
            <% team = bid_info[:team] %>
            <% assigned_team = @assigned_teams_by_topic[topic.id].include?(team) %>
            <span class="<%= assigned_team ? 'assigned-team' : '' %>">
              <%= team.name %> (#<%= bid_info[:priority] %>)
            </span>
          <% end %>
        </td>
        <td>
          <% if @count1[topic.id] != 0%>
            <%= @count1[topic.id] %>
          <%else%>
            No bids yet
          <%end%>
        </td>
        <td>
          <% if @count2[topic.id] != 0%>
            <%= @count2[topic.id] %>
          <%else%>
            No bids yet
          <%end%>
        </td>
        <td>
          <% if @count3[topic.id] != 0%>
            <%= @count3[topic.id] %>
          <%else%>
            No bids yet
          <%end%>
        </td>
      </tr>
    <% end %>
  </tbody>
</table>

<a href="javascript:history.back()">Back</a>

3. The button of View Bidding Details

File: ./app/assignments/edit/_topics.html.erb

<%= button_to 'View Bidding Details', {:controller => 'lottery', :action => 'bidding_details', :id => @assignment_form.assignment.id}, 
:method => :get, class: 'custom-button', id: 'bidding-button' %>

4. RSpec Testing on "bidding_details" Method

File: ./spec/controllers/lottery_controller_spec.rb

Structure:

1. Setup (before :each block):

  • Initializes a testing environment before each test case.
  • Sets up parameters (like assignment.id) to mimic a real request context.

2. Test Case 1: Populating Bids and Assigned Teams

  • Objective: To test if the #bidding_details method correctly populates bids and assigned teams for each topic, including handling topics with no teams.
  • Execution: Calls the #bidding_details method.
  • Expectations:
    • @bids_by_topic should correctly map topics to their respective bids.
    • @assigned_teams_by_topic should correctly map topics to their assigned teams, handling cases where no teams are assigned.
    • Counts of bids for each priority level (@count1, @count2, @count3) are checked against expected values.

3. Test Case 2: Fetching All Topics

  • Objective: To verify if the method fetches all topics related to the assignment.
  • Execution: Invokes #bidding_details.
  • Expectation: The @topics instance variable should contain an array of all topics (e.g., [topic1, topic2, topic3, topic4]).


describe '#bidding_details' do
    before :each do
      # Set the assignment id in the params
      params = ActionController::Parameters.new(id: assignment.id)
      allow(controller).to receive(:params).and_return(params)
    end
    it 'populates bids and assigned teams for each topic, handling topics with no teams' do
      controller.bidding_details
      # Check if @bids_by_topic is populated correctly
      expect(controller.instance_variable_get(:@bids_by_topic)[topic1.id].length).to eq(1)
      expect(controller.instance_variable_get(:@bids_by_topic)[topic2.id].length).to eq(1)
      # Check if @assigned_teams_by_topic is populated correctly, allowing for no teams
      assigned_teams_topic1 = controller.instance_variable_get(:@assigned_teams_by_topic)[topic1.id]
      if assigned_teams_topic1
        expect(assigned_teams_topic1.length).to(satisfy { |value| (value == 0) || (value == 1) })
      else
        expect(assigned_teams_topic1).to be_nil
      end
      # Check the counts of bids for each priority level
      # Ensure to adjust these based on what is set up in your test data
      expect(controller.instance_variable_get(:@count1)[topic1.id]).to eq(1) # assuming there is one bid with priority 1 for topic1
      expect(controller.instance_variable_get(:@count2)[topic1.id]).to eq(0) # assuming there are no bids with priority 2 for topic1
      expect(controller.instance_variable_get(:@count3)[topic1.id]).to eq(0) # assuming there are no bids with priority 3 for topic1
    end

    it 'fetches all topics for the assignment' do
      controller.bidding_details
      expect(controller.instance_variable_get(:@topics)).to match_array([topic1, topic2, topic3, topic4])
    end
  end

Relevant Links

Github Repository: https://github.com/Shreshth-Malik/expertiza

Testing Credentials

username: instructor6

password: password

Team

Mentor

Edward F. Gehringer (efg@ncsu.edu)

Members

Richard Li (rli14@ncsu.edu)

Shreshth Malik (smalik4@ncsu.edu)

Shuai Chen (schen76@ncsu.edu)