Generación de informes
Parte de la sección Lógica y Flujo del Journey de C# de Coddy. Lección 44 de 66.
Desafío
IntermedioAhora que tenemos el sistema de calificaciones, creemos un módulo de informes para generar informes formateados sobre el rendimiento de los estudiantes. Crea una clase llamada ReportGenerator con estos métodos:
GenerateStudentReport(int[][] scoreGrid, int studentIndex): Devuelve una cadena formateada que informa de las calificaciones, el promedio y la calificación con letra de un estudiante específico.- Formato: "Student #X | Average: YY.Y | Grade: Z\nAssignment scores: S1, S2, S3, ..." donde S1, S2, S3, ... son las calificaciones numéricas de cada tarea.
- Para las tareas sin calificar (calificación de -1), muestra "N/A" en lugar de la calificación.
- Devuelve "Invalid student index" para cualquier índice de estudiante no válido.
GenerateClassSummary(int[][] scoreGrid): Devuelve una cadena formateada que resume el rendimiento de la clase.- Formato: "Class Summary\nTotal Students: X\nClass Average: YY.Y\nGrade Distribution: A: #, B: #, C: #, D: #, F: #"
GenerateAssignmentReport(int[][] scoreGrid, int assignmentIndex): Devuelve una cadena formateada con estadísticas de una tarea específica.- Formato: "Assignment #X | Average: YY.Y | Completion Rate: Z%"
- La tasa de finalización es el porcentaje de estudiantes que tienen una calificación para esta tarea (no -1).
- Devuelve "Invalid assignment index" para cualquier índice de tarea no válido.
Pruébalo tú mismo
using System; // No borres esta línea
using System.Text;
public class ReportGenerator
{
public static string GenerateStudentReport(int[][] scoreGrid, int studentIndex)
{
// Escribe tu código aquí
}
public static string GenerateClassSummary(int[][] scoreGrid)
{
// Escribe tu código aquí
}
public static string GenerateAssignmentReport(int[][] scoreGrid, int assignmentIndex)
{
// Escribe tu código aquí
}
}
// Requerido para las pruebas - no modificar
public class DataCollector
{
public static int[][] CreateScoreGrid(int students, int assignments)
{
int[][] scoreGrid = new int[students][];
for (int i = 0; i < students; i++)
{
scoreGrid[i] = new int[assignments];
}
return scoreGrid;
}
public static bool ValidateScore(int score)
{
return score >= 0 && score <= 100;
}
public static int[][] PopulateWithDefaultValues(int[][] scoreGrid)
{
for (int i = 0; i < scoreGrid.Length; i++)
{
for (int j = 0; j < scoreGrid[i].Length; j++)
{
scoreGrid[i][j] = -1;
}
}
return scoreGrid;
}
}
public class DataEntry
{
public static int SetStudentScore(int[][] scoreGrid, int studentIndex, int assignmentIndex, int score)
{
// Comprueba si los índices están fuera de rango
if (studentIndex < 0 || studentIndex >= scoreGrid.Length ||
assignmentIndex < 0 || assignmentIndex >= scoreGrid[studentIndex].Length)
{
return -1;
}
// Valida la puntuación
if (!DataCollector.ValidateScore(score))
{
return -2;
}
// Establece la puntuación
scoreGrid[studentIndex][assignmentIndex] = score;
return 0;
}
public static int UpdateAllScores(int[][] scoreGrid, int[] studentIndices, int assignmentIndex, int score)
{
int successCount = 0;
for (int i = 0; i < studentIndices.Length; i++)
{
int result = SetStudentScore(scoreGrid, studentIndices[i], assignmentIndex, score);
if (result == 0)
{
successCount++;
}
}
return successCount;
}
}
public class DataAnalyzer
{
public static double CalculateStudentAverage(int[][] scoreGrid, int studentIndex)
{
// Check if student index is valid
if (studentIndex < 0 || studentIndex >= scoreGrid.Length)
{
return -1;
}
int sum = 0;
int count = 0;
// Calcula la suma de las puntuaciones válidas
for (int j = 0; j < scoreGrid[studentIndex].Length; j++)
{
int score = scoreGrid[studentIndex][j];
if (score != -1) // Ignora las tareas sin calificar
{
sum += score;
count++;
}
}
// Devuelve el promedio o 0 si no hay puntuaciones válidas
return count > 0 ? (double)sum / count : 0;
}
public static double CalculateAssignmentAverage(int[][] scoreGrid, int assignmentIndex)
{
// Comprueba si hay algún estudiante
if (scoreGrid.Length == 0)
{
return -1;
}
// Check if assignment index is valid
if (assignmentIndex < 0 || assignmentIndex >= scoreGrid[0].Length)
{
return -1;
}
int sum = 0;
int count = 0;
// Calcula la suma de las puntuaciones válidas para la tarea
for (int i = 0; i < scoreGrid.Length; i++)
{
if (assignmentIndex < scoreGrid[i].Length)
{
int score = scoreGrid[i][assignmentIndex];
if (score != -1) // Ignora las tareas sin calificar
{
sum += score;
count++;
}
}
}
// Devuelve el promedio o 0 si no hay puntuaciones válidas
return count > 0 ? (double)sum / count : 0;
}
public static int[] FindHighestScore(int[][] scoreGrid)
{
int highestStudentIndex = 0;
int highestAssignmentIndex = 0;
int highestScore = -1;
// Busca la puntuación más alta
for (int i = 0; i < scoreGrid.Length; i++)
{
for (int j = 0; j < scoreGrid[i].Length; j++)
{
int currentScore = scoreGrid[i][j];
if (currentScore > highestScore)
{
highestScore = currentScore;
highestStudentIndex = i;
highestAssignmentIndex = j;
}
}
}
return new int[] { highestStudentIndex, highestAssignmentIndex, highestScore };
}
}
public class GradingSystem
{
public static string ConvertToLetterGrade(double score)
{
if (score < 0 || score > 100)
{
return "N/A";
}
else if (score >= 90)
{
return "A";
}
else if (score >= 80)
{
return "B";
}
else if (score >= 70)
{
return "C";
}
else if (score >= 60)
{
return "D";
}
else
{
return "F";
}
}
public static string GetStudentGrade(int[][] scoreGrid, int studentIndex)
{
double average = DataAnalyzer.CalculateStudentAverage(scoreGrid, studentIndex);
if (average == -1)
{
return "N/A";
}
return ConvertToLetterGrade(average);
}
public static int[] GetClassDistribution(int[][] scoreGrid)
{
int[] distribution = new int[5]; // [A, B, C, D, F]
for (int i = 0; i < scoreGrid.Length; i++)
{
string grade = GetStudentGrade(scoreGrid, i);
switch (grade)
{
case "A":
distribution[0]++;
break;
case "B":
distribution[1]++;
break;
case "C":
distribution[2]++;
break;
case "D":
distribution[3]++;
break;
case "F":
distribution[4]++;
break;
// N/A grades are not counted in the distribution
}
}
return distribution;
}
}Todas las lecciones de Lógica y Flujo
1Arrays multidimensionales
Conceptos básicos de arrays 2DDeclaración e inicialización de arrays 2DAcceso a elementos de arrays 2DBucles anidados con arrays 2DArrays irregularesOperaciones comunes con matricesRepaso: arrays multidimensionales4Técnicas de control de flujo
Retornos anticipadosCláusulas de guardaSentencias de salto (goto)Break y ContinueAplanar condicionales anidados7Operadores lógicos avanzados
Evaluación de cortocircuitoOperadores lógicos condicionalesPrecedencia de operadoresRepaso: operadores avanzados2Toma de decisiones avanzada
Múltiples condicionesLógica booleana complejaComparación entre If y SwitchSentencias Switch anidadasRepaso: decisiones avanzadas5Manejo de excepciones
Fundamentos de Try-CatchTipos de excepcionesMúltiples bloques CatchTrabajo con archivosBloque FinallyUso de Using frente a Try-FinallyExcepciones personalizadasRepaso: manejo de errores8Sistema de análisis de datos
Configuración de recopilación de datosLógica de entrada de datos3Mejoras de bucles
Rendimiento de buclesIteración de estructuras complejasCada tipo de bucleRefactorización de buclesRepaso: bucles optimizados6Manejo de valores nulos
Conceptos básicos de referencias nulasTipos de valor anulablesPatrones de comprobación de valores nulosProgramación defensivaRepaso: seguridad frente a valores nulosPractica por tu cuenta: Compilador de C# online