结对第二次作业——编程实现

222200429谢雨欣 2024-09-30 23:13:15
这个作业属于哪个课程24秋-软件工程&实践-W班
这个作业要求在哪里结对第二次作业——编程实现
结对学号222200333, 222200429
这个作业的目标使用web技术实现原型的功能
其他参考文献构建之法

目录

  • 一、git仓库链接和代码规范链接
  • 二、PSP表格
  • 三、成品展示
  • 3.1 基础功能
  • 3.1.1首页
  • 3.1.2 奖牌榜
  • 3.1.3 每日赛程
  • 3.1.4 对阵图
  • 3.2 附加功能
  • 3.2.1 详细赛况
  • 3.2.2 个人奖牌榜
  • 3.2.3 了解更多
  • 四、结对讨论过程描述
  • 五、设计实现过程
  • 5.1 技术路线设计
  • 六、代码说明
  • 6.1 导航栏实现
  • 6.2 奖牌榜
  • 6.3 每日赛程
  • 6.4 对阵表
  • 6.5 详细赛况
  • 七、心路历程和收获
  • 八、评价
  • 九、其他

一、git仓库链接和代码规范链接

PSPPersonal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划2020
• Estimate估计这个任务需要多少时间2020
Development开发11901350
• Analysis需求分析 (包括学习新技术)6030
• Design Spec生成设计文档6050
• Design Review设计复审3050
• Coding Standard代码规范 (为目前的开发制定合适的规范)2020
• Design具体设计300340
• Coding具体编码600660
• Code Review代码复审60180
• Test测试(自我测试,修改代码,提交修改)6020
Reporting报告9090
• Test Repor测试报告3030
• Size Measurement计算工作量3030
• Postmortem & Process Improvement Plan事后总结, 并提出过程改进计划3030
合计13001460

三、成品展示

3.1 基础功能

3.1.1首页

  • 首页导航栏
  • 展示奥运咨询和风采图片
  • 奥运奖牌榜、每日赛程、详细赛况的快捷入口

    在这里插入图片描述


    在这里插入图片描述


    在这里插入图片描述

3.1.2 奖牌榜

  • 展示所有参赛国家的获奖情况,按照获取的金、银、铜牌数进行排名

    在这里插入图片描述

3.1.3 每日赛程

  • 页面展示每日赛程
  • 可以通过日期选择器切换日期
  • 可以通过🥇/🥈/🥉/√ 图片快速找到每场比赛获胜者

    在这里插入图片描述

3.1.4 对阵图

在这里插入图片描述

3.2 附加功能

3.2.1 详细赛况

  • 提供小组赛、晋级赛、奖牌赛标签选择,可切换滚动面板展示内容
  • 选择对应的赛程,可见详细赛况,包括:出赛名单、比赛详情
  • 在这里插入图片描述


    在这里插入图片描述

3.2.2 个人奖牌榜

  • 展示所有参赛选手的获奖情况(不包含团体赛),按照获取的金、银、铜牌数进行排名

    在这里插入图片描述

3.2.3 了解更多

  • 展示奥运咨询和风采图片

在这里插入图片描述

四、结对讨论过程描述

222200429 谢雨欣 负责前端
222200333 曾雅婷 负责后端
最开始我们本来打算按照纯前端做,后面我与我的搭档探讨了一下,我们觉得Json数据有点乱,不方便提取,正好我的搭档习惯使用python写后端,便于处理数据。所以我们最后转用前后端实现。在实现过程中,由于我接口这部分比较不熟悉,从纯前端改前后端对接的时候改了很久,我的搭档也很耐心的帮了我很多。
以下是我们的一部分聊天截图

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述

五、设计实现过程

  • 功能结构图

在这里插入图片描述

5.1 技术路线设计

前端:vue3
后端:python
前端接口:Ajax
后端接口:Flask

六、代码说明

6.1 导航栏实现

前端:在components里面创建了一个导航栏组件NavBar.vue,设置好导航栏的样式,尽可能还原原型设计,并对我的导航栏添加了动态效果,添加超链接实现跳转页面功能,在App.vue中引用它,使得导航栏位于每个页面的顶端。

在这里插入图片描述

6.2 奖牌榜

前端:

  • 由于后面改成前后端对接,时间不够,奖牌榜我采用的是最简单的表格样式。国家国旗的显示我们是通过从后端接收国家名称缩写,访问网址引用图片。个人金牌榜的实现方式和国家奖牌榜大同小异,只是接收的数据不同。

    在这里插入图片描述


    在这里插入图片描述


    后端:
  • 数据处理&通过接口响应前端请求
  • 传递"noc"值便于放置国旗
  • 关于个人奖牌榜的数据处理

(1)在json文件中找到所有有关数据并进行统计处理


for item in data['props']['pageProps']['initialMedals']['medalStandings']['medalsTable']:
    for discipline in item['disciplines']:
        for winner in discipline['medalWinners']:

            if winner['competitorType']=="A":
                competitorName = winner['competitorDisplayName']
                countryName = item['longDescription']
                noc=item['organisation'],
                medalType = winner['medalType']
            
                if medalType == 'ME_GOLD':
                    medal_stats[competitorName]['gold'] += 1
                elif medalType == 'ME_SILVER':
                    medal_stats[competitorName]['silver'] += 1
                elif medalType == 'ME_BRONZE':
                    medal_stats[competitorName]['bronze'] += 1

                medal_stats[competitorName]['country'] = countryName
                medal_stats[competitorName]['noc'] = noc


for name in medal_stats:
    stats = medal_stats[name]
    stats['total'] = stats['gold'] + stats['silver'] + stats['bronze']

(2)根据统计数据对选手进行排名并赋值排名


medal_info_sorted = sorted(
    [
        (name, stats['country'], stats['noc'][0], stats['gold'], stats['silver'], stats['bronze'], stats['total']) 
        for name, stats in medal_stats.items()
    ],
    key=lambda x: (-x[6],-x[3], -x[4], -x[5])  
)

(3)json数据结构


playerMedals=[
    {
        "rank":i+1,
        "competitorName": entry[0],
        "countryName": entry[1],
        "noc":entry[2],
        "gold": entry[3],
        "silver": entry[4],
        "bronze": entry[5],
        "total": entry[6]
    }
    for i,entry in enumerate(medal_info_sorted)
]

6.3 每日赛程

前端:

  • 使用 <input type="date"> 创建一个日期选择器,允许用户选择日期。使用<div>标签和v-for指令循环展示每场比赛的信息,从起始日期开始,生成19个连续的日期。在脚本部分,我定义了一些方法来处理用户交互和数据操作。

  • getScorePrefix(team):根据队伍的奖牌类型返回相应的图标路径。

  • handleDateChange():当用户选择日期时,这个方法会被调用,用于从后端获取比赛数据。

    在这里插入图片描述


    后端:

  • 数据处理&简单接口传值。

    6.4 对阵表

    前端:

  • 对阵表的连线其实我一开始不知道怎么实现,我问了几个同学,试了几个方法,最后在figma上实现连线导出图片,并调整图片位置渲染效果。

    在这里插入图片描述

    6.5 详细赛况

    前端:

  • 我定义了一个selectedGroupMatches属性来获取当前选中组别的比赛信息和一个totalPages属性来计算总页数。

  • 我定义了一个fetchMatchesData方法来获取比赛数据,使用axios向后端发送请求并处理响应。

  • 我定义了一个方法来处理组别的选择,更新selectedGroup和currentPage,并重新获取数据。

在这里插入图片描述


后端:

  • 数据处理
    (1)html页面元素定位(非常需要耐心细心分析的一步)

出赛名单数据处理:
最开始定位时发现会有许多其他相同class值的无关数据被读取,需要通过观察结构、打印调试等方式确认所需元素的确切位置。还需要对读取到的信息进行处理,格式可能包含换行符。


for i, table in enumerate(tables):
        tbody = table.find('tbody', role='rowgroup')
        if tbody:
            for tr in tbody.find_all('tr'):
                number = tr.find('td', role='cell', class_='text-end')
                cells = tr.find_all('td', role='cell', class_='text-start')
                if len(cells) == 2:
                    comp_container = cells[0].find('a', class_='competitor-container')
                    name = comp_container.find('span', class_='competitor-long-name d-none d-sm-inline-block text-truncate').text.strip() if comp_container else ""
                    name = clean_string(name) if name else ""
                    position = cells[1].text.strip()

                    player = Player(number, name, position)

                    if i == 0:
                        starters_a.append(player.to_dict())
                    elif i == 1:
                        substitutes_a.append(player.to_dict())
                    elif i == 3:
                        starters_b.append(player.to_dict())
                    elif i == 5:
                        substitutes_b.append(player.to_dict())

    for i, row in enumerate(rows):
        if i == 1:
            countryName_a = row.find('span', class_='competitor-long-name d-none d-sm-inline-block text-truncate').text.strip()
        if i == 2:
            coach_a = row.find('span', class_='competitor-long-name d-none d-sm-inline-block text-truncate')
            coach_a = clean_string(coach_a.text) if coach_a else ""

        if i == 6:
            countryName_b = row.find('span', class_='competitor-long-name d-none d-sm-inline-block text-truncate')
            countryName_b = clean_string(countryName_b.text) if countryName_b else ""

        if i == 7:
            coach_b = row.find('span', class_='competitor-long-name')
            coach_b = clean_string(coach_b.text) if coach_b else ""

详细赛况数据处理:
需要逐步找到页面元素并处理。


    soup=BeautifulSoup(content,'html.parser')

    accordion=soup.find('div',class_='accordion')

    H1=accordion.find('div',id='mirs-accordion-item-H1')

    H2=accordion.find('div',id='mirs-accordion-item-H2')

    h1Body=H1.find('div',class_='accordion-body')

    h2Body=H2.find('div',class_='accordion-body')

    h1Rows=h1Body.find_all('div',class_='row')

    h2Rows=h2Body.find_all('div',class_='row')

    # 处理First Half
    for i,row in enumerate(h1Rows):
        time=row.find('div',class_='box-center text-center flex-column').find('div')
        time = clean_string(time.text) if time else ""

        infor=row.find('div',class_='box flex-column flex-nowrap')
        infor=clean_string(infor.text) if infor else ""

        gameInfor = GameInfor(time,infor)

        h1GameINfor.append(gameInfor.to_dict())

    # 处理Second Half
    for i,row in enumerate(h2Rows):
        time=row.find('div',class_='box-center text-center flex-column').find('div')
        time = clean_string(time.text) if time else ""

        infor=row.find('div',class_='box flex-column flex-nowrap')
        infor=clean_string(infor.text) if infor else ""

        gameInfor = GameInfor(time,infor)

        h2GameINfor.append(gameInfor.to_dict())

(2)json数据结构

出赛名单:


data = {
        "id": id, # id 为对应的比赛分组和比赛编号 例如 1A 3C
        "country_a": {
            "countryName": countryName_a,
            "coach": coach_a,
            "starters": starters_a,
            "substitutes": substitutes_a
        },
        "country_b": {
            "countryName": countryName_b,
            "coach": coach_b,
            "starters": starters_b,
            "substitutes": substitutes_b
        }
    }

详细赛况:


data ={
            "id":id,
            "H1GameInfors":h1GameINfor,
            "H2GameInfors":h2GameINfor
    }

(3)批量处理数据文件


html_files = glob.glob('rawinfor/*F.html')
  • 相应前端带参数的请求并返回响应数据

接收两个参数,组别、比赛编号,根据组别查找数据文件,根据比赛编号和组别合成的值定位所需数据。


# 出赛名单
@app.route('/entryList',methods=['GET'])
def entryList():
    group=request.args.get('group')
    id=request.args.get('id')
    id_value=f"{id}{group}"
    print(f"id_value: {id_value}")

    file_name=f"{group}s.json"
    file_path=os.path.join('data/processinfor',file_name)

    if os.path.exists(file_path):
        with open(file_path,'r',encoding='utf-8') as f:
            data=json.load(f)

            for item in data:
                if item['id']==id_value:
                    print("entrylist sucess")
                    return (item),200
                    
        return jsonify({"error":"id not found"}),404
    else :
        return jsonify({"error":"File not found"}),404

七、心路历程和收获

谢雨欣:
心路历程:我的项目经验较少,且给的时间并不多,我在原型设计结束不久就开始着手实现原型,我担心写的太慢会拖搭档的后腿。我之前写过项目的前端,但接口的部分我还不熟悉,我请教了团队中前端的负责人和我的搭档。在完成项目的过程中我们也遇到了很多问题,我们一点点的修改,完善。我们很用心在完成这次作业。
曾雅婷:
心路历程:这次编程作业熟悉了网站信息爬取,利用python进行、数据处理、写接口,以及与前后端的接口对接。网站爬取还是无法利用脚本,只能通过找包含内容的页面元素手动爬取,并编写脚本解析html文件获得数据。python很适合写这个简单的后端。在前后端对接的过程中,增进了对网络通信的理解,也认识到了沟通协作的重要性。不过这次任务还是完成得太极限了,还是应该考虑清楚自己的能力范围,量力而行即可。

八、评价

谢雨欣:选择纯前端转前后端对接的时候我很担心,我的搭档鼓励我并安慰我,在对接过程中也帮了我很多。我的搭档积极上进,应变能力强,及时分享进度且基础很好,这次的结对作业虽然很辛苦但也收获了很多。
曾雅婷:我的队友非常可靠,非常值得信任。她能够提前的规划和着手工作并且效率很好,是非常值得学习的。在遇到困难的时候也能及时告知,共同解决问题,保持项目的健康进度。此次作业我们挑战了很多难点,并最终有惊无险地完成了任务。

九、其他

  • 数据爬取行为仅用于课程教学
...全文
250 2 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
助教林泽源 2024-10-15
  • 打赏
  • 举报
回复

首页,了解更多功能中的内容设置为中文,才不会中文,英文这么突兀。

222200429谢雨欣 2024-10-16
  • 举报
回复
@助教林泽源 好的,我们会积极改进,谢谢助教
AJAX——新手快车道 前言 AJAX是什么? 首先、AJAX是一种很酷的技术,一旦采用了AJAX,就能让你的Web页面, 你的网站,甚至连同你们公司,都变得很酷。在Web2.0的时代里,不使用一点 AJAX技术的网站,就会显得很老土,很落伍。 但是,这样的理解,其实是很肤浅的。仅仅是从一个外行,从一个使用者的 角度出发,来理解AJAX,就像我在本书的第一章AJAX我也行中那样,开发 出很愚蠢,甚至都没有资格被称之为AJAX应用的纯IE、XMLHTTP应用。 AJAX更酷的一点在于,对于传统的Web开发人员来说,AJAX所运用的, 是更加先进的,更加标准化的,更加和谐高效的,完整的Web开发技术体系。 遵循这样的体系开发Web应用,能让你的开发过程变得更加轻松,也能使你们 的开发团队,显得很酷。在Web2.0 的时代里,还在采用过时的技术来开发 Web,会显得很老土,很落伍。 AJAX的相关组成技术,每一个都已经出现了N年以上了,对这些技术的 组合运用,也远远早于AJAX这个名词出现之前。所以,我真正敬佩的,并非提 出 AJAX这个缩写的Jesse James Garrett。而是那些早在N年以前,就已经在探索、 实践的先行者,他们始终在追求的:是更好的用户体验,以及更好的开发体验。 这样的精神,才是最可宝贵的,也是最值得我们学习的。许多年过去以后,当我 们再回头来看当年的这些热门技术,也许早已经变得老土,变得落伍了。在这样 的历程中,哪些人会成长为高手?会成长为大师呢?就是那些永不满足,永远 在追求更好的用户体验,永远在追求更好的开发体验的人! 新手如何上路 软件开发这个领域,永远都在飞速发展,大家都必须不断的学习新的知识、 技能、框架、IDE、甚至新的语言。传说中的骨灰级高手们,就像传说中的大侠, 任何武器、哪怕是一块木头到了他们手里,也能发挥惊人的威力,人家练了几十 年的看家本领,他们随手使来,也竟然像是打娘胎里就开始练了一样。为什么? 就算不吹那么玄的,平常我们能够碰到的那些老手,在学新东西的时候, 也比那些新手学得更快,理解得更深,运用得更熟练。而新手们呢?往往就会漫 无头绪,焦头烂额,以一副张着茫然的大眼睛的经典表情,出现在各大论坛的 新手求助区里。他们欠缺的,究竟是什么呢?为什么老手学新东西,就没遇到那 么多困难呢? 泛泛地说,自然是经验上的欠缺。仔细地说来,又可以分为三个方面: 一、本质,一种技术与另一种技术之间,往往会有本质上的相通之处,当你 对一种技术的理解与思考越来越深入时,学习一种新技术也会更加容易。触类旁 通,举一反三的能力,就是来自于对于技术本质的追寻。 二、地图,本质上或多或少的相通,也提示着我们技术之间的相互关联,当 你了解的技术越多,了解得越是深入,在你的内心,就能建立起越发清晰的技 术地图。各种知识都有一个自然、合理的位置。那么当一个老手要学习一门新技术 的时候,他其实并非在探索一个全新的、未知的领域,而是有很多脉络可寻,也 很多已知可以帮助他们快速了解未知。 三、技巧,面对同样的未知,面对同样的难题,新手们一筹莫展,而老手们 却掌握着更多的技巧和手段,帮助他们试探可能性、缩小问题的范围、迅速定位 问题、不犯明显愚蠢的错误、甚至能够列举出更具命中力的搜索关键词,而这些 技巧,都帮助老手在前进的道路上,更少跌倒,即使跌倒,也能更快的爬起来。 作为一本写给新手的入门书籍,我们希望展现给读者的,是一个老手如何 学习新技术的过程。我们相信,这样的一个学习过程,对于新手来说,是更具有 价值的。 何谓快车道 必须老老实实的承认,我吹牛了!老手虽然会比新手学习得更快一些,但 是也同样会碰到麻烦,遇到障碍,感觉头痛。如果没有真正的专家的指导,我不 可能如此迅速地将AJAX掌握到目前这样的程度,要真是让我自学三个月,然 后就写出书来的话,那真是在骗钱了。 老手能够快速学习的另一个重要的诀窍是:认识很多牛人朋友 如果没有李锟与赵泽欣的专家级指导与帮助,如果没有与李锟AJAX结对 编程的体验,如果没有三个人在MSN上无数次的长聊,我想要在短期内建立起: 对于AJAX本质的理解; 对于整个AJAX以及相关技术地图的理解; 对于AJAX编程开发所需要的很多技巧、手段的掌握; 几乎是不可能的。 如果没有(N多需要感谢的人)的(N多方面的帮助),我们这本书,也 不可能以现在这样的深度,以(N个月)内完成的速度,送到读者的面前。 希望这本书,能够对大家快速学习AJAX,有所帮助。

239

社区成员

发帖
与我相关
我的任务
社区管理员
  • FZU_SE_teacherW
  • 助教赖晋松
  • D's Honey
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧