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

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很适合写这个简单的后端。在前后端对接的过程中,增进了对网络通信的理解,也认识到了沟通协作的重要性。不过这次任务还是完成得太极限了,还是应该考虑清楚自己的能力范围,量力而行即可。

八、评价

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

九、其他

  • 数据爬取行为仅用于课程教学
...全文
127 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
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,有所帮助。

110

社区成员

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

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