File size: 6,235 Bytes
6e6e8e8
bd5a999
6e6e8e8
d51b6cd
6e6e8e8
 
 
d51b6cd
16495d2
1ea0fc8
6e6e8e8
16495d2
d51b6cd
 
 
 
 
 
 
 
16495d2
d51b6cd
16495d2
d51b6cd
 
 
 
 
 
 
 
 
 
 
 
 
6e6e8e8
d51b6cd
 
6e6e8e8
 
16495d2
 
 
 
d51b6cd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6e6e8e8
d51b6cd
 
 
 
 
 
 
 
 
 
 
 
 
 
6e6e8e8
d51b6cd
6e6e8e8
 
 
 
 
bd4642a
6e6e8e8
 
d51b6cd
 
6e6e8e8
 
 
d51b6cd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27a356c
6e6e8e8
27a356c
 
6e6e8e8
 
 
 
 
 
 
 
 
 
 
 
d51b6cd
6e6e8e8
 
 
d51b6cd
6e6e8e8
 
 
 
 
bd5a999
d51b6cd
6e6e8e8
 
 
 
bd5a999
 
d51b6cd
6e6e8e8
bd5a999
6e6e8e8
d51b6cd
6e6e8e8
 
d51b6cd
 
 
 
 
6e6e8e8
d51b6cd
6e6e8e8
d51b6cd
 
 
 
 
6e6e8e8
d51b6cd
6e6e8e8
d51b6cd
16495d2
 
d51b6cd
 
 
 
 
 
 
 
 
 
6e6e8e8
 
 
 
 
 
 
 
 
 
 
d51b6cd
bd5a999
6e6e8e8
 
 
bd5a999
 
 
d51b6cd
6e6e8e8
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# Load required libraries
library(shiny)
library(readxl)
library(tidyverse)
library(stringr)
library(openxlsx)


# Define the timeout period in seconds
timeoutSeconds <- 1200

# Create the JavaScript code to handle user inactivity
inactivity <- sprintf("
function idleTimer() {
    var t;
    var timeout = %s * 1000; // Convert seconds to milliseconds

    // Events that reset the timer
    var events = ['mousemove', 'mousedown', 'click', 'scroll', 'keypress'];

    // Function to log out and notify the user
    function logout() {
        alert('You have been disconnected due to inactivity. Refresh your browser to use the webapp again. - Dr. Eduardo');
        Shiny.setInputValue('timeOut', '%s');
    }

    // Function to reset the timer
    function resetTimer() {
        clearTimeout(t);
        t = setTimeout(logout, timeout);
    }

    // Attach resetTimer to each event
    events.forEach(function(event) {
        window.addEventListener(event, resetTimer);
    });

    // Initialize the timer
    t = setTimeout(logout, timeout);
}

// Initialize the idle timer when the document is ready
document.addEventListener('DOMContentLoaded', function() {
    idleTimer();
});
", timeoutSeconds, timeoutSeconds)


#####
read_and_preprocess <- function(path, filename) {
  df <- read_excel(path)
  
  # Remove columns with entirely NA entries
  df <- df[, colSums(is.na(df)) != nrow(df), drop = FALSE]
  
  columns_selected <- c("ID number", "Last name", "Time taken", "State", "Grade/5.00")
  new_column_names <- c("ID_Number", "Last_Name", "Time_Taken", "State", "Grade")
  
  # Select and rename columns
  df <- df[, columns_selected, drop = FALSE]
  colnames(df) <- new_column_names
  
  # Convert Grade to numeric and Last_Name to title case
  df$Grade <- as.numeric(df$Grade)
  df$Last_Name <- str_to_title(df$Last_Name)
  
  # Remove rows with missing values
  df <- df[complete.cases(df), ]
  
  return(df)
}

# Function to calculate additional columns
calculate_additional_columns <- function(df, attempted, filename) {
  avg_col_name <- paste("Average", filename, sep = "_")
  
  df <- df %>%
    group_by(ID_Number) %>%
    mutate(nAttempt = n(),
           !!avg_col_name := ifelse(nAttempt >= attempted,
                                    round(mean(sort(Grade, decreasing = TRUE)[1:attempted]),0),
                                    round(sum(Grade) / attempted))) %>%
    distinct(ID_Number, .keep_all = TRUE)
  
  return(df)
}
#####



# Define UI
ui <- fluidPage(
  #tags$script(HTML(inactivity)),
  titlePanel(
    h4("UTAS - Online Marks Aggregator"),
    windowTitle = "Marks Aggregator"
  ),
  
  sidebarLayout(
    sidebarPanel(
      numericInput(
        "attempt",
        "Min Number of Attempts",
        value = 1, min = 1, max = 10, step = 1
      ),
      
      fileInput(
        "files",
        "Upload Excel file(s)",
        accept = c(".xlsx"),
        multiple = TRUE,
        placeholder = "Please select excel file/s"
      ),
      
      helpText("Upload only Excel files with .XLSX extension to ensure consistency."),
      br(),
      downloadButton("downloadData", "Download"),
      hr(),
      
      div(
        class = "fluent-footer",
        div(
          class = "fluent-footer-legal",
          div(
            class = "fluent-footer-legal-left",
            a("Privacy Policy", href = "#"),
            " | ",
            a("Terms of Use", href = "#")
          ),
          div(
            class = "fluent-footer-legal-right",
            "© 2023 College of Computing and Information Sciences"
          )
        )
      ),
      
      tags$footer(
        style = "text-align: left; padding-top: 10px; font-size: 12px;",
        "Built by ",
        tags$a(href = "https://www.google.com/search?q=dr.+eduardo+lacap+jr&sca_esv=4136c3af1df3852c&sca_upv=1&sxsrf=ADLYWIIeq7fb1cWKSiyieFVwGRe7qJ40NA%3A1716361100562&ei=jJdNZqHvIZbeseMPj4O8sAs&oq=dr.+eduardo+lacap&gs_lp=Egxnd3Mtd2l6LXNlcnAiEWRyLiBlZHVhcmRvIGxhY2FwKgIIATIHECMYsAMYJzIHECMYsAMYJzILEAAYgAQYsAMYogQyCxAAGIAEGLADGKIEMgsQABiwAxiiBBiJBTILEAAYgAQYsAMYogRIuA1QAFgAcAF4AJABAJgBAKABAKoBALgBAcgBAJgCAaACBJgDAIgGAZAGBpIHATGgBwA&sclient=gws-wiz-serp", "Dr. Eduardo M. Lacap, Jr.")
      )
    ),
    
    mainPanel(
      tableOutput("table")
    )
  )
)


# Define server logic
server <- function(input, output, session) {
  
  # Reactive expression for the number of attempts
  attempted <- reactive({ input$attempt })
  
  # Reactive expression for the nature of the files uploaded
  
  independnt <- reactive({input$independent})
  
  # Reactive expression to read and combine uploaded Excel files
  combined_df <- reactive({
    req(input$files$datapath)  # Ensure files are uploaded
    
    df_list <- mapply(function(path, name) {
      df <- read_and_preprocess(path, tools::file_path_sans_ext(basename(name)))
      df <- calculate_additional_columns(df, attempted(), tools::file_path_sans_ext(basename(name)))
      return(df)
    }, input$files$datapath, input$files$name, SIMPLIFY = FALSE)
    
    combined_df <- bind_rows(df_list)
    
    combined_df <- if (length(df_list) == 1) {
      df_list[[1]] %>% 
        select(ID_Number, Last_Name, starts_with("Average"))
    } else {
          as.data.frame(combined_df) %>%
          select(ID_Number, Last_Name, starts_with("Average")) %>% 
          pivot_longer(cols = starts_with("Average_"), names_to = "Average_Type", values_to = "Average_Value") %>%
          filter(!is.na(Average_Value)) %>%
          pivot_wider(names_from = "Average_Type", values_from = "Average_Value") %>% 
          mutate_at(., vars(starts_with("Average_")), ~replace(., is.na(.), 0), values_fn = list) %>%  
          mutate(Marks = round(rowMeans(select(., starts_with("Average_")), na.rm = TRUE)+0.1,0))
      }
    return(combined_df)
  })
  
  
  # Display combined data as a table
  output$table <- renderTable({
    combined_df()
  })
  
  # Download combined data
  output$downloadData <- downloadHandler(
    filename = function() {
      paste("MarksAggregated_", attempted(), "_MinAttempt.xlsx", sep = "")
    },
    content = function(file) {
      write.xlsx(combined_df(), file)
    }
  )
}


# Run the application
shinyApp(ui = ui, server = server)