109
社区成员
这个作业属于哪个课程 | 2401_CS_SE_FZU |
---|---|
这个作业要求在哪里 | 结对第二次作业——编程实现 |
结对学号 | 222200223,222200210 |
这个作业的目标 | 基于 Web 技术实现原型中的功能 |
其他参考文献 | 《构建之法》 |
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 30 |
• Estimate | • 估计这个任务需要多少时间 | 30 | 30 |
Development | 开发 | 1300 | 1610 |
• Analysis | • 需求分析(包括学习新技术) | 300 | 350 |
• Design Spec | • 生成设计文档 | 50 | 50 |
• Design Review | • 设计复审 | 30 | 20 |
• Coding Standard | • 代码规范(为目前的开发制定合适的规范) | 30 | 60 |
• Design | • 具体设计 | 300 | 400 |
• Coding | • 具体编码 | 400 | 720 |
• Code Review | • 代码复审 | 30 | 60 |
• Test | • 测试(自我测试,修改代码,提交修改) | 150 | 200 |
Reporting | 报告 | 110 | 135 |
• Test Report | • 测试报告 | 40 | 60 |
• Size Measurement | • 计算工作量 | 30 | 15 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 40 | 60 |
合计 | 1440 | 2025 |
附加功能导航栏:每个页面顶部都有设置导航栏,能够通过导航栏前往首页,奖牌榜页,赛程页面和了解更多页面。
主页提供轮播图来让用户观看精彩赛事图片
奖牌榜排名显示
展示每一天的赛事,显示比赛类型(足球、七人制橄榄球、手球等),比赛时间,比赛项目,参赛国家和比赛比分,且获胜国家加粗显示
支持通过切换日期查看不同的赛程
支持点击查看详细赛程信息
比赛晋级图是一种直观的展示比赛进程和结果的工具,它以图表的形式呈现了参赛在各个阶段的表现。
鼠标移动到某一场比赛需要高亮或显示边框提示。
介绍巴黎奥林匹克运动会的举办背景,通过丰富的图文使平台更具吸引力,引起人们对巴黎奥林匹克运动会的兴趣。
了解完本次作业要求后,通过分析可知本次作业主要展示2024巴黎奥运会的相关信息,包括奖牌榜、每日赛程和详细赛程,并且数据需要各自进行爬取。因此,我们决定使用后端进行对数据的爬取,运用JSP来处理大量的JSON数据文件,并动态加载不同日期或赛事的详细信息。
设计思路:
扩展功能:
问题一:动态读取其他网页的数据不稳定并且耗时较长
解决方式:直接用后端将数据爬取成json文件,进行本地读取。
public static void main(String[] args) {
String startDate = "2024-07-24";
String endDate = "2024-08-11";
LocalDate start = LocalDate.parse(startDate);
LocalDate end = LocalDate.parse(endDate);
List<Map<String, Object>> allResults = new ArrayList<>();
for (LocalDate date = start; !date.isAfter(end); date = date.plusDays(1)) {
try {
List<Map<String, Object>> dailyResults = fetchScheduleDataWithRetries(date.toString());
allResults.addAll(dailyResults);
} catch (Exception e) {
System.err.println("Error fetching data for date " + date + ": " + e.getMessage());
}
}
allResults.sort((map1, map2) -> map1.get("startDate").toString().compareTo(map2.get("startDate").toString()));
allResults.forEach(System.out::println);
}
public static List<Map<String, Object>> fetchScheduleData(String date) throws Exception {
String urlString = "https://sph-s-api.olympics.com/summer/schedules/api/CHI/schedule/day/" + date;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(urlString))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
throw new RuntimeException("Failed to fetch data: HTTP error code " + response.statusCode());
}
return parseJsonData(response.body());
}
这段代码是一个用于显示奥运会赛程的网页应用程序的片段。它使用了JSP(JavaServer Pages)技术来动态生成网页内容。以下是代码的详细思路:
日期选择器表单:用户可以通过表单选择日期来查看特定日期的奥运会赛程。
input
元素用于选择日期,readonly
属性表示用户不能直接输入日期,只能通过选择器选择。后台逻辑(JSP脚本):
request.getParameter("selectedDate")
获取用户选择的日期参数。如果用户没有选择日期,默认设置为 "2024-07-24"。JSONParser
解析JSON文件内容,将赛事信息存储在 JSONArray
对象中。如果文件存在且解析成功,赛事信息将被加载到 events
数组中。前端展示(JSTL标签):
<c:forEach>
标签迭代 events
数组中的每个事件。<div class="content">
<div class="container">
<h1>奥运赛程</h1>
<!-- 日期选择器 -->
<form method="get">
<label for="datepicker">选择日期:</label>
<input type="text" id="datepicker" name="selectedDate" readonly />
<button type="submit">查看赛程</button>
</form>
<%
String selectedDate = request.getParameter("selectedDate");
if (selectedDate == null || selectedDate.isEmpty()) {
selectedDate = "2024-07-24"; // 默认日期
}
// 构建JSON文件路径
String filePath = application.getRealPath("/data/" + selectedDate + ".json");
File jsonFile = new File(filePath);
JSONArray events = new JSONArray();
if (jsonFile.exists()) {
JSONParser parser = new JSONParser();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(jsonFile), "UTF-8"))) {
Object obj = parser.parse(reader);
events = (JSONArray) obj;
} catch (Exception e) {
e.printStackTrace();
}
}
pageContext.setAttribute("events", events);
%>
<!-- 使用 JSTL 标签来迭代事件 -->
<c:forEach var="event" items="${events}">
<a href="detail.jsp?eventId=${event.id}" style="text-decoration:none;color:black;">
<div class="event">
<div class="time">${event.startDate.substring(11,16)}</div>
<div class="sport">
${event.disciplineName} - ${event.eventUnitName}
</div>
<!-- 显示竞争者 -->
<c:if test="${not empty event.competitor1Name}">
<div class="team">
<img src="https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/${event.competitor1Noc}.png" alt="${event.competitor1Noc} flag" class="flag">
<span class="team-name" style="${event.mark1 > event.mark2 ? 'font-weight:bold;' : ''}">
${event.competitor1Name}
</span>
<div class="score-container">
<span class="score">${event.mark1}</span>
</div>
</div>
</c:if>
<c:if test="${not empty event.competitor2Name}">
<div class="team">
<img src="https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/${event.competitor2Noc}.png" alt="${event.competitor2Noc} flag" class="flag">
<span class="team-name" style="${event.mark2 > event.mark1 ? 'font-weight:bold;' : ''}">
${event.competitor2Name}
</span>
<div class="score-container">
<span class="score">${event.mark2}</span>
</div>
</div>
</c:if>
</div>
</a>
</c:forEach>
</div>
</div>
这段JavaScript代码用于在详细赛况上动态显示和分页展示比赛信息。它提供了一个交互式界面,让用户能够查看比赛详情并通过分页按钮浏览不同的比赛页。以下是代码的详细介绍:
数据初始化:
matches
:包含比赛信息的数组,由服务器端通过 gson.toJson(matches)
转换为JSON格式并嵌入到JavaScript中。currentPage
和 itemsPerPage
:用于控制分页逻辑,分别表示当前页码和每页显示的比赛数量。函数定义:
**renderMatches()
**:
currentPage
和 itemsPerPage
计算当前页应显示的比赛范围。**updatePaginationButtons()
**:
**prevPage()
和 nextPage()
**:
**highlightButton(button)
**:
**highlightMatch(matchDiv)
**:
事件绑定:
renderMatches()
函数以初始化比赛展示。<script>
var matches = <%= gson.toJson(matches) %>;
var currentPage = 0;
var itemsPerPage = 3;
function renderMatches() {
var container = document.getElementById('matchContainer');
container.innerHTML = '';
var start = currentPage * itemsPerPage;
var end = Math.min(start + itemsPerPage, matches.length);
for (var i = start; i < end; i++) {
var match = matches[i];
var competitorsHtml = match.competitors.map(function(c) {
var flagUrl = "https://gstatic.olympics.com/s1/t_original/static/noc/oly/3x2/180x120/" + c.noc + ".png";
return '<div style="display:flex; align-items:center; justify-content:space-between;">' +
'<div><img src="' + flagUrl + '" alt="' + c.noc + ' Flag" style="height:20px; margin-right:5px;"> ' +
c.name + '</div><div>' + c.mark + '</div></div>';
}).join('');
var matchDiv = document.createElement('div');
matchDiv.className = 'match';
matchDiv.innerHTML = '<h3>' + match.eventUnitName + ', 比赛 ' + match.order + '</h3>' +
competitorsHtml +
'<p style="display:flex; justify-content:space-between;">' +
'<span>' + new Date(match.startDate).toLocaleString('zh-CN', { month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric' }) +
'</span><span>已结束</span></p>';
// 添加点击事件监听器以实现高亮效果
matchDiv.addEventListener('click', function() {
highlightMatch(this);
});
container.appendChild(matchDiv);
}
updatePaginationButtons();
}
function updatePaginationButtons() {
var prevButton = document.querySelector('.pagination-buttons button:first-child');
var nextButton = document.querySelector('.pagination-buttons button:last-child');
prevButton.disabled = currentPage === 0;
nextButton.disabled = (currentPage + 1) * itemsPerPage >= matches.length;
}
function prevPage() {
if (currentPage > 0) {
currentPage--;
renderMatches();
}
}
function nextPage() {
if ((currentPage + 1) * itemsPerPage < matches.length) {
currentPage++;
renderMatches();
}
}
window.onload = function() {
renderMatches();
// 默认选中第一个按钮
var firstButton = document.querySelector('.nav-buttons .button');
highlightButton(firstButton);
};
function highlightButton(button) {
// 移除所有按钮的 'selected' 类
var buttons = document.getElementsByClassName('button');
for (var i = 0; i < buttons.length; i++) {
buttons[i].classList.remove('selected');
}
// 为点击的按钮添加 'selected' 类
button.classList.add('selected');
}
function highlightMatch(matchDiv) {
// 移除所有比赛卡片的 'selected' 类
var matches = document.getElementsByClassName('match');
for (var i = 0; i < matches.length; i++) {
matches[i].classList.remove('selected');
}
// 为点击的比赛卡片添加 'selected' 类
matchDiv.classList.add('selected');
}
</script>
222200223徐玮辰:
通过这个项目,我对前端需求的理解更加深入,这使我能够为队友提供更清晰、更易用的数据结构和接口。通过与队友的紧密合作,我也更加重视代码质量和可维护性,我们共同审查和优化代码,确保系统的稳定性和性能。最重要的是,我体验到了团队合作的价值和乐趣。与优秀的前端开发人员一起工作,不仅让我在技术上有所提升,也让我学会了如何更好地倾听、沟通和协作。这种团队合作的经验将在我未来的软件开发项目中发挥重要作用。
222200210苏臻炜:
在这次项目中,我最大的收获是团队合作带来的成长和自信。本次由我来进行jsp代码编写,队友进行数据的获取,让我拥有一次很好的jsp网页设计经验。这种经验让我对未来的项目挑战充满信心,我相信团队合作的力量能够带来更多的成功。同时,我也意识到软件工程是一条需要不断学习和改进的道路,每一次的实践都是一次宝贵的经验,让我能够不断反思和提升自己。通过这次实践,我对自己的能力和潜力有了更深的理解,并对未来充满期待。
222200223徐玮辰:
队友富有远见和谋略,并且善于分配任务,可以成为一个可靠的小组或团队的核心人员。并且他的前端技术水平过硬,在项目中,他总是能够高效地调用我提供的数据,实现前端页面的创作。在他的帮助下我对前端技术有了更深刻的理解,受益匪浅。
222200210苏臻炜:
队友在团队合作中展现了出色的精神,始终保持认真负责的态度,时间观念强,所有任务都在规划下有序地完成。在项目中,队友的数据模块设计和实现为整个项目奠定了坚实的基础,他提供的清晰数据结构使我能够轻松理解和实现前端页面的功能。同时,队友对代码性能优化的关注给我留下了深刻的印象,我们共同克服了技术难题,取得了令人满意的成果。