这个作业属于哪个课程 | 202302软件工程实践 |
---|---|
这个作业要求在哪里 | 结对第二次作业–编程实现 |
结对学号 | 222100410、222100412 |
这个作业的目标 | 学习前后端开发框架、编码实现原型设计、部署网站到云服务器上、编写博客汇报 |
其他参考文献 | 《构建之法》 |
1.Git仓库链接和代码规范链接
1.1 Gitcode仓库链接
1.2 代码规范链接
2.PSP表格
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 40 |
Estimate | 估计这个任务需要多少时间 | 30 | 40 |
Development | 开发 | 1550 | 1960 |
Comunicate | 讨论开发流程与使用框架 | 30 | 30 |
Analysis | 技术学习 | 500 | 600 |
Coding Standard | 代码规范 | 30 | 30 |
Coding | 具体编码 | 900 | 1200 |
Code Review | 代码复审 | 30 | 40 |
Test | 测试 | 60 | 60 |
Reporting | 报告 | 290 | 340 |
Test Repor | 博客编写 | 240 | 300 |
Size Measurement | 计算工作量 | 10 | 10 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 30 | 30 |
合计 | 1870 | 2340 |
3.成品展示
3.1 云服务器访问链接(点击进入)
3.2 整体设计风格
- 首页我们继续根据原型设计保持每个页面统一的顶端导航栏和标题图,并且使用契合游泳主题的白蓝色继续作为主色调,整体风格保持简介明了,能让用户以最短的时间获取自己想要的信息
3.3 首页(基础功能)
- 首页部分使用选手风采的轮播图来凸显世界游泳锦标赛的主题
- 下方插入了赛事简介,丰富首页内容
3.4 赛程(基础功能)
- 赛程部分左上角插入日期选择器方便选取日期,下方会展示当天的赛程信息
- 为了突出总决赛的重要性,我们把Final用金色高亮表示并附加了一个奖牌图标
- 如果没你选择的日期没有比赛的话,就会显示如下
3.5 排名(基础功能)
- 排名部分左上角插入赛事选择器方便选取赛事
- 下方会展示该赛事的选手的排名和年龄,以及得分与分差
3.6 选手(基础功能)
- 展示选手的国籍、性别、出生年月日的信息
3.7 了解更多(附加功能)
- 了解更多页面方面,我们整理了2024所有赛事的排名一览图,方便访客快速了解本次赛程的基本情况,并且用各种图片来丰富单一的文字界面,降低审美疲劳(拓展功能)
4.结对讨论过程描述
4.1 分工安排及讨论截图
- 整体分工大概是222100410zhm做首页、赛程、了解更多,222100412ljc做排名和选手部分
- 关于PTS Behind数据的编写讨论
- 关于赛事数据使用的讨论
4.2 结对讨论实拍图
5.设计实现过程
5.1 功能结构图
5.2 开发项目使用的技术
- 考虑到时间紧迫,我们决定使用html+css+js纯前端的方式来进行开发
- 开发软件为VS Code
5.3 git提交情况
6.代码说明
6.1 导航栏及标题
- HTML
<head>
<title>导航页面</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="header">
<h1>世界游泳锦标赛</h1>
</div>
<!-- 导航栏容器 -->
<div class="navbar">
<button href="#" onclick="showPage('home')">首页</button>
<button href="#" onclick="showPage('schedule')">赛程</button>
<button href="#" onclick="showPage('ranking')">排名</button>
<button href="#" onclick="showPage('athletes')">选手</button>
<button href="#" onclick="showPage('detail')">了解更多</button>
</div>
6.2 首页部分
- HTML
<div id="home" class="page">
<!-- 轮播图容器 -->
<div class="slideshow-container">
<div class="mySlides fade">
<img src="image/home1.jpg" style="width:100%">
</div>
<div class="mySlides fade">
<img src="image/home2.jpg" style="width:100%">
</div>
<div class="mySlides fade">
<img src="image/home3.jpg" style="width:100%">
</div>
<div class="mySlides fade">
<img src="image/home4.jpg" style="width:100%">
</div>
</div>
<!-- 简介容器 -->
<div class="intro">
<img src="image/intro.png" style="width:100%">
</div>
</div>
- JavaScript
var slideIndex = 0;
function showSlides() {
var slides = document.getElementsByClassName("mySlides");
for (var i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
slideIndex++;
if (slideIndex > slides.length) {
slideIndex = 1;
}
slides[slideIndex - 1].style.display = "block";
setTimeout(showSlides, 2000); // 切换时间间隔为 2 秒
}
function showPage(pageId) {
// 隐藏所有页面
var pages = document.getElementsByClassName("page");
for (var i = 0; i < pages.length; i++) {
pages[i].classList.remove("active");
}
// 显示指定页面
var page = document.getElementById(pageId);
if (page) {
page.classList.add("active");
}
}
showSlides(); // 初始调用
window.onload = function () {
showPage('home');
};
6.3 赛程部分
- HTML
<div id="schedule" class="page">
<!-- 日期选择器容器 -->
<div class="date-selector">
<input type="date" id="date-selector" value="2024-01-18">
</div>
<!-- 赛程信息容器 -->
<div id="event-info"></div>
</div>
- JavaScript
const dateSelector = document.getElementById('date-selector');
const eventInfo = document.getElementById('event-info');
dateSelector.addEventListener('change', () => {
const selectedDate = dateSelector.value;
eventInfo.innerHTML = ''; // 清空之前的内容
eventdata.Sports[0].DisciplineList.forEach(item => {
item.HeatList.forEach(eventItem => {
if (eventItem.Date === selectedDate) {
const eventElement = document.createElement('div');
eventElement.textContent = `${eventItem.Time} - ${item.DisciplineName} `;
eventElement.classList.add('event-element');
const eventName = document.createElement('span');
eventName.textContent = eventItem.Name;
if (eventItem.IsFinal) {
const medalIcon = document.createElement('img');
medalIcon.src = './image/medal.png';
medalIcon.classList.add('medal-icon');
eventElement.appendChild(medalIcon);
eventName.classList.add('final-event');
}
eventElement.appendChild(eventName);
var button = document.createElement("button");
var eventDetail = "Event Detail";
button.innerText = eventDetail;
button.style.backgroundColor = "transparent";
button.classList.add('event-detail');
eventElement.appendChild(button);
eventInfo.appendChild(eventElement);
}
}
);
});
if (eventInfo.children.length === 0) {
const noEventElement = document.createElement('div');
noEventElement.textContent = `No event on ${selectedDate}`;
eventInfo.appendChild(noEventElement);
}
});
6.4 排名部分
- HTML
<div id="ranking" class="page">
<!-- 赛事选择器容器 -->
<select id="event-selector">
<option value="m1sp">Men 1m Springboard</option>
<option value="m3sp">Men 3m Springboard</option>
<option value="m3sy">Men 3m Synchronised</option>
<option value="m10pl">Men 10m Platform</option>
<option value="m10sy">Men 10m Synchronised</option>
<option value="w1sp">Women 1m Springboard</option>
<option value="w3sp">Women 3m Springboard</option>
<option value="w3sy">Women 3m Synchronised</option>
<option value="w10pl">Women 10m Platform</option>
<option value="w10sy">Women 10m Synchronised</option>
</select>
<div class="rankline">
<img src="image/rankline.png" style="width:100%">
</div>
<!-- 排名信息容器 -->
<div id="rank-info"></div>
</div>
- JavaScript
const eventSelector = document.getElementById('event-selector');
const rankInfo = document.getElementById('rank-info');
eventSelector.addEventListener('change', () => {
const selectedevent = eventSelector.value;
rankInfo.innerHTML = ''; // 清空之前的内容
var rankdata = dataMap[selectedevent];
var top_point = rankdata.Heats[0].Results[0].TotalPoints;
rankdata.Heats[0].Results.forEach(athlete => {
const rankElement = document.createElement('div');
var athAge = athlete.AthleteResultAge;
if (!athlete.hasOwnProperty("AthleteResultAge")) {
athAge = 'unknown';
}
rankElement.textContent = `${athlete.Rank} - ${athlete.FullName} - ${athlete.TotalPoints} - ${athAge} - ${top_point - athlete.TotalPoints}`;
rankElement.classList.add('rank-element');
rankInfo.appendChild(rankElement);
});
});
6.5 选手部分
- HTML
<div id="athletes" class="page">
<div class="athleteline">
<img src="image/athleteline.png" style="width:100%">
</div>
<div id="athletes-info"></div>
</div>
- JavaScript
var athletedata = JSON.parse(athletesJsonString);
const athletesInfo = document.getElementById('athletes-info');
athletedata.forEach(country => {
country.Participations.forEach(
athlete => {
const athletesElement = document.createElement('div');
var gender = "Men";
if (athlete.Gender = 1) {
gender = "Women";
}
athletesElement.textContent = `${athlete.PreferredLastName} ${athlete.PreferredFirstName} - ${country.CountryName} - ${gender} - ${athlete.DOB}`;
athletesElement.classList.add('rank-element');
athletesInfo.appendChild(athletesElement);
}
)
}
);
6.6 了解更多部分
<div id="detail" class="page">
<div class="detail">
<img src="image/detail.png" style="width:100%">
</div>
</div>
7.心路历程和收获
7.1 222100410zhm的心路历程
这次作业之前,我对前端开发一直都不算特别擅长,因此为了完成本次作业,我花费了不少的时间去学习前端知识,并且最后完成了大体的功能。除此之外我还负责收集图片和界面设计的部分,补充了一些细节,这次作业显著地锻炼了我的前端代码编写能力,并且同时在与队友合作过程中加强了git使用和代码仓合作编程的能力,总的来说这一次作业还是比较令我满意的,完成了基本的功能和一些拓展功能,希望能进一步精进我的代码能力
7.2 222100412ljc的心路历程
这次作业由于只涉及前端的部分,相较于本来计划中前后端要简单很多,由于原型设计大部分是我队友完成的,我便按照队友的设计完成配合他完成了应有的功能;这次作业加强了我在前端方面的编程能力,我相信加强前端代码编写能力会对我的将来有很大的帮助
8.评价结对队友
8.1 222100412ljc to 222100410zhm:
zhm在这次结对过程中,担任起了设计原型和后续前端美化和界面设计的重任,按照他的想法我们合作完成了本次的作业,由于我本人主攻后端开发,对于界面设计和调试这种繁琐的事务一直比较抵触,还好有队友的耐心修改才使得此次作业比较完善地展示出来,与他合作很愉快!
8.2 222100410zhm to 222100412ljc:
在整个编程过程中ljc给了我很多关于代码编写方面的指导,能够清晰地指出当前代码编写中一些问题,比如这段代码没有规范性,避免为后续开发埋下bug的伏笔,他本身的编程能力比我强很多,在结对的过程中我也一直虚心的学习和请教他关于代码方面的知识,总的来说他是一个很负责任很有能力的伙伴!