首页 > 编程语言 >开发一个篮球共享计分器小程序

开发一个篮球共享计分器小程序

时间:2025-01-16 16:32:03浏览次数:1  
标签:case log 计分 text 篮球 else break 器小 赛事

序言

  作为一名篮球爱好者的程序员,在使用目前市面篮球计分器时,总觉得用的不顺手,市面基本都是单机模式,广告很多,也不便于核对和多人协同记录。因此,我决定自己设计并开发一款篮球共享计分器小程序,实现多人协同记录赛事,提供多种方便快捷的计分方式和统计数据效果。

  上效果图:

      

  

  由于上篇《开发一个题库系统App和小程序的心得》已经叙述了很多资源方案,代码方案,部署方案,以及很多基础性的功能开发设计,此系统基本相同,不再赘述,直接讲解篮球共享计分器特有功能。

 

1.    功能目标

  篮球共享计分器功能目标:

  1. 实现多人实时共享记录比赛
  2. 提供个人和团队数据和表现的统计数据
  3. 提供单机版/共享版/私密版三种模式记录比赛
  4. 提供简易/精准版模式选择
  5. 保存历史比赛数据,可用于文字直播。

 

1.1     功能列表

  篮球共享计分器核心功能

  1. 实现常规简易单机版计分器
  2. 实现协同协同版计分器,协同实时切换简易版和精准版计分方式
  3. 实现团队对比数据,可视化图表展示和对比,以及完整文字记录
  4. 实现个人完整数据,以及个人完整文字记录
  5. 协同版区分公开和私密赛事,公开赛事可免登录参与,私密赛事支持多种精准权限控制记录比赛

 

1.2     功能截图

  以下是App端的部分截图

       

  以下是微信小程序端的部分截图

       

2.    实现方案

 

2.1     设计方案

 

2.1.1   数据库设计

  赛事表

   

 

  队员表

   

 

  授权表

   

 

  日志表

   

  

2.1.2   移动端开发-赛事列表和录入

        

           

  

  赛事有三种添加方式:

  1. 已有比赛,可以选择复制一份,会复制赛事的队员和用户权限
  2. 录入比赛,自行录入比赛名称等信息,保存即可
  3. (需登录)添加授权码比赛,别人创建的私密比赛,分享的授权码,可以通过授权码进行添加

 

  赛事录入细节:

  1. 长按赛事明细,可操作复制/编辑/授权/重置/取消/删除(可见操作按钮跟权限有关)
  2. 编辑赛事,可增加/修改/删除赛事双方队员:添加队员直接录入即可;搜索队员可查找有权限赛事的所有人员,因此同名队伍只需录入一次,下次直接搜索一次性添加即可;长按队员可编辑;删除按钮可删除。(赛事录入页面也可同样操作)

  

2.1.3   移动端开发-赛事授权(需登录)

  赛事列表中,对于公开赛事,所有人都可见也都是管理员角色;对于私密赛事,长按明细,可选择授权操作。

       

       

  有两种授权模式:

  1. 生成授权码,点击观众/主队管理员/客队管理员/管理员,可生成对应赛事授权码,其他人在赛事列表页面通过添加授权码比赛的方式即可获权
  2. 添加用户,点击添加用户,输入用户信息查找授权即可(为保证用户隐私,此处不支持模糊搜索)

 

  授权细节说明:

  1. 赛事创建人是超级管理员,可以直接添加/修改/删除任何已授权用户
  2. 只能添加/修改/删除比自己低的权限,不会出现操作的权限超越操作人的权限的情况
  3. 可自己删除自己的授权,删除后赛事不可见

 

2.1.4   移动端开发-记录比赛

       

  赛事记录方法:

  1. 点击【精准版】/【简易版】可以互相切换记录模式
  2. 点击【用时】,可查看实时比赛数据结果
  3. 点击【分享比赛】,可生成赛事二维码,让其他人参与
  4. 长按任意队员,可切换队员
  5. 长按日志明细,可作废或修改日志

  赛事记录说明:

  1. 公开赛事记录,所有人都是管理员权限,都可以通过分享的二维码进行赛事记录。
  2. 私密赛事记录,扫码进来的默认赋权观众,需要进一步授权才可以记录比赛,否则只能观看。
  3. 私密赛事记录,管理员可以记录双方数据,主队管理员只能记录主队数据,客队管理员只能记录客队数据,观众只能观看。
  4. 加时赛说明,默认四节比赛,如果在第四节结束,两队分数一致,自动进入加时,否则比赛结束。

 

2.1.5   移动端开发-查看结果

       

       

  

  查看结果有三种方式:

  1. 列表已经结束的比赛,点击查看即可查看比赛结果
  2. 记录比赛中,点击用时可以查看比赛结果
  3. 通过其他人分享的比赛结果二维码可以查看比赛结果

 

  查看结果操作说明:

  1. 进入结果页面,可点击上方【*** 数据】切换页签,也可以左右滑动切换页签
  2. 在【**队 数据】页签,柱状图的“其他”表示整队的数据,也就是比赛记录时,选择了队伍,未选择具体人员
  3. 小程序图表可能出现空白,点一下图表内部,即可正常显示,图表组件在小程序上的层级Bug问题,暂时未修复

 

2.1.6   移动端开发-单机版计分器

    

 

  操作说明:

  1. 点击【单机版】可清空重置数据
  2. 长按【犯规】或【队伍暂停】可减少次数
  3. 打开页面后可离线操作,离开页面或应用,数据缓存在本地,并不会消失,只能记录一个赛事,清空重置后,数据清除不可找回

 

2.2     开发方案

 

2.2.1   后端开发-框架Springboot

  基于若依plus,在其基础上增加ruoyi-race模块,单独存放赛事相关功能,其中四个controller分别是:

    

  Race:赛事功能

  Log:日志功能

  Member:成员功能

  User:授权用户功能

  Message:SSE发送消息功能(已弃用)

  SSE:SSE连续功能(已弃用)

  WxToken:获取小程序Token和生成小程序带参数二维码功能

  

  SSE在使用时,微信小程序和APP不能很好的支持EventSource前端组件,长连接也存在兼容问题,效果都不好,所以弃用,使用WebSocket

    

        在整合的框架中,使用的是Tio引擎的Websocket,增加两种赛事的消息类型,初始化消息和常规消息:

        初始化消息:读取并回执当前某一赛事最新完整赛事数据

        常规消息:发送记录赛事时的各种指令,更新赛事,记录日志,并回执更新后的完整赛事数据


 

2.2.2   移动端开发-框架Uniapp

核心在记录赛事使用websocket上,这里我们使用具体页面直连的方式,离开页面则关闭websocket,相关代码如下

    onUnload() {
        this.timeClear()
        this.socket.close(true)
    },
    onShow() {
        this.diyApiGet('/race/race/getMoreByRaceId/' + this.setData.id).then(res => {
            this.setData = res.data;
            if(!this.userInfo || !this.userInfo.userId){
                // 公开赛事,无用户,随机生成一个
                this.userId = this.getRandom(2, 16);
            }else{
                this.userId = this.userInfo.userId;
            }
            // websocket非通讯状态,则重连
            // #ifdef APP-PLUS
            if(!this.socket){
                this.getMemberFirstList();
                this.getMemberSecondList();
                this.connectWebsocket(this.userId, this.setData.id);
            }
            // #endif
            // #ifndef APP-PLUS
            if(!this.socket || this.socket.getReadyState() != 1){
                this.getMemberFirstList();
                this.getMemberSecondList();
                this.connectWebsocket(this.userId, this.setData.id);
            }
            // #endif
        })
    },


连接websocket方法,未登录传入随机用户ID

    connectWebsocket(userId, raceId){
            let url = globalData.wssUrl;
            let heartbeatTimeout = 50000; // 心跳超时时间,单位:毫秒
            let reconnInterval = 5000; // 重连间隔时间,单位:毫秒
            let binaryType = 'blob'; // 'blob' or 'arraybuffer';//arraybuffer是字节
            let paramStr = "app=urace&userId=" + userId + "&sessionId=" + raceId
            let param = "";
            this.socket = new TioSocket(url, paramStr, param, heartbeatTimeout, reconnInterval, binaryType);
            let ws = this.socket.connect(false);
            
            ws.onOpen((e) => {
                // 读取赛事初始信息
                uni.sendSocketMessage({
                    data: JSON.stringify({code:6, message: {raceId: raceId, userId: userId}})
                })
              this.socket.reset();
            })
            ws.onMessage((e) => {
                let message = JSONbig.parse(e.data);
                if(message.code == 2){
                    let data = JSONbig.parse(message.message.content)
                    if(data.msg){
                        this.msg(data.msg);
                        return;
                    }
                    if(data.data){
                        this.setData = data.data;
                        this.usedTime = data.data.usedTime || 0;
                        if(data.data.status == 1){
                            this.timeInterval();
                        }else{
                            this.timeClear();
                        }
                        if(data.data.status < 0){
                            this.logList = []
                        }
                        this.showTitle();
                    }
                    if(data.log){
                        if(data.log.logType == 99){
                            this.getMemberFirstList();
                            this.getMemberSecondList();
                            this.invalidMessageLog(data.log)
                        }else if(data.log.logType == 61){
                            this.moveMessageLog(data.log)
                        }else{
                            if(data.log.logType == 34 || data.log.logType == 41 || data.log.logType == 42 || data.log.logType == 43 
                                || data.log.logType == 81 || data.log.logType == 82 || data.log.logType == 83){
                                if(data.log.teamIndex == 1){
                                    this.getMemberFirstList();
                                }
                                if(data.log.teamIndex == 2){
                                    this.getMemberSecondList();
                                }
                            }
                            this.addMessageLog(data.log, true)
                        }
                    }
                }
                this.socket.reset();
            })
        },


赛事记录命令转译函数

export function getLogText(log, firstTeamName, secondTeamName, status){
    let text = "";
    if(log.teamIndex == 1){
        text += " " + firstTeamName
    }
    if(log.teamIndex == 2){
        text += " " + secondTeamName
    }
    if(log.memberName){
        text += " " + log.memberName
    }
    switch(log.logType){
        case -10:
            text += "比赛尚未开始";
            break;
        case -1:
            text += "比赛进行中";
            break;
        case -2:
            text += "比赛暂停中";
            break;
        case -3:
            if(log.period == 2){
                text += "第一节已结束";
            }else if(log.period == 3){
                text += "第二节已结束";
            }else if(log.period == 4){
                text += "第三节已结束";
            }else if(log.period >= 5 && log.firstTeamScore != log.secondTeamScore){
                text += "比赛已结束";
            }else if(log.period == 5){
                text += "第四节已结束";
            }else if(log.period == 6){
                text += "加时赛1已结束";
            }else if(log.period == 7){
                text += "加时赛2已结束";
            }else if(log.period == 8){
                text += "加时赛3已结束";
            }else if(log.period == 9){
                text += "加时赛4已结束";
            }else if(log.period == 10){
                text += "加时赛5已结束";
            }else{
                text += "加时赛已结束";
            }
            break;
        case -9:
            text += "比赛已取消";
            break;
        case 1:
            text += "比赛开始";
            break;
        case 2:
            text += "裁判暂停";
            break;
        case 3:
            if(log.period == 1){
                text += "第一节比赛继续";
            }else if(log.period == 2){
                text += "第二节比赛继续";
            }else if(log.period == 3){
                text += "第三节比赛继续";
            }else if(log.period == 4){
                text += "第四节比赛继续";
            }else if(log.period == 5){
                text += "加时赛1继续";
            }else if(log.period == 6){
                text += "加时赛2继续";
            }else if(log.period == 7){
                text += "加时赛3继续";
            }else if(log.period == 8){
                text += "加时赛4继续";
            }else if(log.period == 9){
                text += "加时赛5继续";
            }else if(log.period == 10){
                text += "加时赛6继续";
            }else{
                text += "加时赛继续";
            }
            break;
        case 4:
            if(log.period == 2){
                text += "第一节结束";
            }else if(log.period == 3){
                text += "第二节结束";
            }else if(log.period == 4){
                text += "第三节结束";
            }else if(log.period >= 5 && log.firstTeamScore == log.secondTeamScore){
                text += "比赛结束";
            }else if(log.period == 5){
                text += "第四节结束";
            }else if(log.period == 6){
                text += "加时赛1结束";
            }else if(log.period == 7){
                text += "加时赛2结束";
            }else if(log.period == 8){
                text += "加时赛3结束";
            }else if(log.period == 9){
                text += "加时赛4结束";
            }else if(log.period == 10){
                text += "加时赛5结束";
            }else{
                text += "加时赛结束";
            }
            break;
        case 5:
            text += "比赛取消";
            break;
        case 6:
            text += " 请求暂停";
            break;
        case 11:
            text += " 罚篮命中,得1分"
            break;
        case 12:
            text += " 投篮命中,得2分"
            break;
        case 13:
            text += " 投篮命中,得2分,加罚1次"
            break;
        case 14:
            text += " 突破上篮,得2分"
            break;
        case 15:
            text += " 突破上篮,得2分,加罚1次"
            break;
        case 16:
            text += " 投篮命中,得3分"
            break;
        case 17:
            text += " 投篮命中,得3分,加罚1次"
            break;
        case 18:
            text += " 扣篮成功,得2分"
            break;
        case 19:
            text += " 扣篮成功,得2分,加罚1次"
            break;
        case 20:
            text += " 扣1分"
            break;
        case 21:
            text += " 罚篮不中"
            break;
        case 22:
            text += " 2分不中"
            break;
        case 23:
            text += " 2分不中,被犯规,罚球2次"
            break;
        case 24:
            text += " 3分不中"
            break;
        case 25:
            text += " 3分不中,被犯规,罚球3次"
            break;
        case 26:
            text += " 上篮失败"
            break;
        case 27:
            text += " 上篮失败,被犯规,罚球2次"
            break;
        case 28:
            text += " 扣篮失败"
            break;
        case 29:
            text += " 扣篮失败,被犯规,罚球2次"
            break;
        case 31:
            text += " 助攻一次"
            break;
        case 32:
            text += " 失误,丢失球权"
            break;
        case 33:
            text += " 抢断,获得球权"
            break;
        case 34:
            text += " 普通犯规"
            break;
        case 35:
            text += " 被普通犯规"
            break;
        case 36:
            text += " 投篮被犯规,开始罚球"
            break;
        case 37:
            text += " 盖帽"
            break;
        case 38:
            text += " 被盖帽"
            break;
        case 39:
            text += " 获得前场篮板"
            break;
        case 40:
            text += " 获得后场篮板"
            break;
        case 41:
            text += " 犯规,对手罚球"
            break;
        case 42:
            text += " 违体犯规"
            break;
        case 43:
            text += " 技术犯规"
            break;
        case 81:
            text += " 上场"
            break;
        case 82:
            text += " 下场," + log.nextMemberName + " 上场"
            break;
        case 83:
            text += " 下场休息"
            break;
        default:
            text += log.logType
    }
    return " " + text
}

 

3.    总结一下

  篮球共享计分器,主要实现的是一个协同处理能力,此次小程序开发,不仅实现了App、小程序、H5的三端兼容,也实现了赛事数据的实时同步,经过测试,任意时间进入赛事的用户,都能保证比赛用时显示的同步,互相操作都能及时收到消息。

 

  不足之处,图表使用的uchart工具,兼容性还有待研究,篮球规则懂的不全面,以及更多形式的赛事记录支持等。

 

  以上分享心得只能描述个大概,个人文档和开发水平都有限,文档或有错误和不妥之处,欢迎指定!

标签:case,log,计分,text,篮球,else,break,器小,赛事
From: https://www.cnblogs.com/Vrapile/p/18675167

相关文章

  • JSP篮球论坛网站设计与实现8lb36(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容一、研究背景与意义篮球运动在全球范围内拥有广泛的爱好者群体,他们渴望有一个交流心得、分享比赛视频的互动平台。然而,现有的篮球论坛大多功能单一......
  • JSP篮球学员信息管理系统i5o70(程序+源码+数据库+调试部署+开发环境
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表技术要求:开发语言:JSP前端使用:HTML5,CSS,JSP动态网页技术后端使用SpringBoot,Spring技术主数据库使用MySQL开题报告内容一、项目背景与意义随着篮球运动的普......
  • 20章12节:多元统计分析的可视化扩展包,从主成分分析到时间序列,从K-means聚类到广义线性
    多元统计分析中的数据可视化是科学研究与分析中不可或缺的一部分,它不仅能够帮助研究者直观地理解数据结构,还能为复杂的统计模型提供清晰的解释。然而,传统的R语言制图方法往往需要较高的学习成本,尤其是对于需要从多种统计包中提取结果并进行可视化的任务。基于此背景,作为一个构......
  • AI磁力聚星提现生成器小游戏提现截图带动态带音效辅助的自定义提现截图生成工具技术研
    AI辅助的自定义提现截图生成工具技术文献本文介绍了一种基于人工智能技术的自定义提现截图生成工具,该工具旨在为用户提供一种便捷、高效的方式来生成磁力小游戏提现截图。通过该工具,用户可以自定义截图内容,包括金额、时间等关键信息,并支持录屏功能,以满足用户在社交媒体分享时......
  • 财务知识-期末常用会计分录
    财务知识-期末常用会计分录 ......
  • 数学建模入门——描述性统计分析
     摘要:本篇博客主要讲解了数学建模入门的描述性统计分析,包括基本统计量的计算、数据的分布形态、数据可视化和相关性分析。往期回顾:数学建模入门——建模流程-CSDN博客数学建模入门——数据预处理(全)-CSDN博客一、基本统计量基本统计量是描述性统计分析的重要组成部分......
  • 大学生HTML期末大作业——HTML+CSS+JavaScript购物商城(篮球)
    HTML+CSS+JS【购物商城】网页设计期末课程大作业web前端开发技术web课程设计网页规划与设计......
  • OKR、KPI与平衡计分卡的系统性对比与应用
    在现代管理实践中,OKR(ObjectivesandKeyResults)、KPI(KeyPerformanceIndicators)和平衡计分卡(BalancedScorecard,BSC)是三种常见的目标设定与管理工具。它们分别适用于不同的管理场景和需求,同时也可以互相结合使用。本文将对其思想、方法、适用场景进行系统性讲解,以便更好地......
  • springboot毕设 吕梁学院篮球竞赛管理系统程序+论文
    系统程序文件列表开题报告内容研究背景在现代高校教育中,体育竞赛不仅是增强学生体质、培养团队精神的重要途径,也是校园文化建设不可或缺的一部分。吕梁学院作为一所充满活力的高等学府,其篮球竞赛活动一直备受师生关注。然而,传统的竞赛管理方式存在诸多不足,如报名流程繁琐、......
  • 区域入侵检测视频分析服务器小知识:视频分析技术的编解码标准性能有哪些?
    在现代数字视频技术迅速发展的背景下,视频编解码标准的性能对视频质量、传输效率以及用户体验产生了显著影响。随着视频内容需求的持续增长,不同标准的出现与演进为各类应用场景提供了更为高效的解决方案。从H.264(AVC)到新兴的AV1,各种编码技术以其各自的优缺点满足了不同行业与用户......