1、背景:朋友请帮忙做一个比赛排程软件

2、需求:

① 比赛人数未知,可以通过文本文件读取参赛人员名称;

② 对参赛人员随机分组,一组两人,两两PK,如果是奇数人数,某一个参赛人员成为幸运儿自动晋级;

③ 比赛线下进行,比赛结束后,可以在线选择每组中晋级人员;

④ 晋级人员进行下一轮比赛分组,依此类推,直至最后一轮。

看完了以上的需求,聪明的你会做出什么样的分析和设计呢?以下是我的愚见。

3、分析:

① 考虑到该朋友的实际情况和业务需求,这个比赛排程软件显然越简单越傻瓜越好,所以在实现架构上不考虑BS架构,而考虑单页面呈现+参赛人员名称文本文档形式。

② 根据需求,大致绘制如下功能示意图,显然这样设计也是为了实现起来方便

4、实现:看到这里,聪明的你肯定有更好的实现方式啦!还请不低赐教哦!以下是我的实现写法

 <!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>汤胖专用_比赛排程器</title>
<style>
label {
color: red;
} div {
display: inline;
margin: 5px;
padding: 2px;
} .initDiv {
background-color: black;
color: white;
} .matchDiv {
background-color: orange;
color: black;
} .playerDiv {
background-color: pink;
color: black;
} .resultDiv {
background-color: green;
color: white;
} .resultData {
background-color: blue;
color: white;
} .selectDiv {
background-color: #666666;
color: white;
}
</style>
</head> <body>
<fieldset>
<legend>汤胖专用_比赛排程器の使用说明</legend>
<ol>
<li>选择的文件必须是utf-8格式</li>
<li>使用Chrome浏览器或360浏览器的极速模式</li>
<li>第一轮排程时,选择要使用的文本文件(参考模板文件)</li>
<li>后续排程时,先点击刷新页面,再点击开始排程,即可使用上轮保存的过关人员</li>
</ol>
</fieldset>
<hr/>
<div>
<input type="file" id="btnFiles" />
<input type="button" id="btnPlan" value="步骤2、开始排程" />
<input type="button" id="btnSave" value="步骤3、保存数据" />
<input type="button" id="btnUpdate" value="步骤4、刷新页面" />
<hr/>
</div>
<script>
var arr = [];
var resultData = []; // 扩展数组功能:实现随机排序
if (!Array.prototype.shuffle) {
Array.prototype.shuffle = function () {
for (var j, x, i = this.length; i; j = parseInt(Math.random() * i), x = this[--i], this[i] =
this[j], this[j] = x);
return this;
};
} // 扩展数组功能:实现删除指定值元素
if (!Array.prototype.removeByValue) {
Array.prototype.removeByValue = function (val) {
for (var i = 0; i < this.length; i++) {
if (this[i] == val) {
this.splice(i, 1);
break;
}
}
};
} // 页面初始化
window.onload = function () {
var btnFiles = document.getElementById('btnFiles');
var btnPlan = document.getElementById('btnPlan');
var btnSave = document.getElementById('btnSave');
var btnUpdate = document.getElementById('btnUpdate'); btnFiles.onchange = importFile;
btnPlan.onclick = matchPlan;
btnSave.onclick = saveData;
btnUpdate.onclick = updatePage;
}; // 以CSS类名获取元素
var getClass = function (classname) {
return document.getElementsByClassName(classname);
}; var importFile = function () {
// 获取读取的File对象
var selectedFile = document.getElementById("btnFiles").files[0];
if (selectedFile.name) {
// 读取选中文件的文件名
var name = selectedFile.name;
// 读取选中文件的大小
var size = selectedFile.size; // 读取操作
var reader = new FileReader();
// 读取文件的内容
reader.readAsText(selectedFile); reader.onload = function () {
// 当读取完成之后会回调这个函数,然后文件内容存储到result
var temparr = this.result.split(/[\s\n]/);
temparr.forEach(function (v, i) {
if (v != '') {
arr.push(v);
}
}); // 第一轮排程时,文本文件内容存储在sessionStorage中,后续均使用sessionStorage
sessionStorage.setItem('resultData', arr);
};
}
}; var matchPlan = function () {
if (sessionStorage.getItem('resultData')) {
arr = sessionStorage.getItem('resultData').split(',');
} var initLabel = document.createElement('label');
initLabel.className = 'initLabel';
initLabel.innerText = '初始数据:';
document.body.appendChild(initLabel); for (var i = 0; i < arr.length; i++) {
var tempdiv = document.createElement('div');
tempdiv.id = 'initDiv' + i;
tempdiv.className = 'initDiv';
tempdiv.innerText = arr[i];
document.body.appendChild(tempdiv);
} // 随机排序
arr.shuffle(); // 换行
document.body.appendChild(document.createElement('br'));
document.body.appendChild(document.createElement('br')); // 显示参赛人员数据
var matchLabel = document.createElement('label');
matchLabel.innerText = '随机排序:';
document.body.appendChild(matchLabel); for (var i = 0; i < arr.length; i++) {
var tempdiv = document.createElement('div');
tempdiv.id = 'matchDiv' + i;
tempdiv.className = 'matchDiv';
tempdiv.innerText = arr[i];
document.body.appendChild(tempdiv);
} document.body.appendChild(document.createElement('hr')); var temp = document.createElement('label');
temp.className = 'initLabel';
temp.innerText = '比赛分组:';
document.body.appendChild(temp); // 换行
document.body.appendChild(document.createElement('br'));
document.body.appendChild(document.createElement('br')); for (var i = 0; i < arr.length; i++) {
if (i % 2 == 0) {
var groupLabel = document.createElement('label');
groupLabel.innerText = "第" + (Math.round(i / 2) + 1) + "组:";
document.body.appendChild(groupLabel); var player1div = document.createElement('div');
player1div.id = 'playerDiv' + i;
player1div.className = 'playerDiv';
player1div.innerText = arr[i];
document.body.appendChild(player1div);
} else {
var groupLabel = document.createElement('label');
groupLabel.className = 'initLabel';
groupLabel.innerText = " VS ";
document.body.appendChild(groupLabel); var player2div = document.createElement('div');
player2div.id = 'playerDiv' + i;
player2div.className = 'playerDiv';
player2div.innerText = arr[i];
document.body.appendChild(player2div); // 换行
document.body.appendChild(document.createElement('br'));
document.body.appendChild(document.createElement('br'));
}
} document.body.appendChild(document.createElement('hr')); var resultLabel = document.createElement('label');
resultLabel.innerText = "过关人员:";
document.body.appendChild(resultLabel); // 换行
document.body.appendChild(document.createElement('br'));
document.body.appendChild(document.createElement('br')); for (var i = 0; i < getClass('playerDiv').length; i++) {
// 获取比赛分组div元素并绑定双击事件
getClass('playerDiv')[i].ondblclick = function () {
// 设置比赛分组div元素双击后不能再被双击
this.style['pointer-events'] = 'none';
this.setAttribute("class", "selectDiv"); var tempdiv = document.createElement('div');
tempdiv.id = 'resultDiv' + i;
tempdiv.className = 'resultDiv';
tempdiv.innerText = this.innerText;
document.body.appendChild(tempdiv); resultData.push(this.innerText); for (var i = 0; i < getClass('resultDiv').length; i++) {
getClass('resultDiv')[i].ondblclick = function () {
document.body.removeChild(this);
resultData.removeByValue(this.innerText); for (var i = 0; i < getClass('selectDiv').length; i++) {
if (this.innerText == getClass('selectDiv')[i].innerText) {
// 设置比赛分组div元素可以被双击
getClass('selectDiv')[i].style['pointer-events'] = 'auto';
getClass('selectDiv')[i].setAttribute("class", "playerDiv");
}
}
};
}
};
}
}; // 保存数据供下一轮排程使用
var saveData = function () {
// 使用HTML5的SessionStorage在当次会话期间在客户端浏览器中存储数据
sessionStorage.setItem('resultData', resultData);
}; // 刷新页面,开始下一轮排程
var updatePage = function () {
window.location.reload();
};
</script>
</body> </html>

实现代码

【原】无脑操作:HTML5 + CSS + JavaScript实现比赛排程的更多相关文章

  1. 【原】无脑操作:EasyUI Tree实现左键只选择叶子节点、右键浮动菜单实现增删改

    Easyui中的Tree组件使用频率颇高,经常遇到的需求如下: 1.在树形结构上,只有叶子节点才能被选中,其他节点不能被选中: 2.在叶子节点上右键出现浮动菜单实现新增.删除.修改操作: 3.在非叶子 ...

  2. 【原】无脑操作:express + MySQL 实现CRUD

    基于node.js的web开发框架express简单方便,很多项目中都在使用.这里结合MySQL数据库,实现最简单的CRUD操作. 开发环境: IDE:WebStorm DB:MySQL ------ ...

  3. 【原】无脑操作:IDEA + maven + Shiro + SpringBoot + JPA + Thymeleaf实现基础授权权限

    上一篇<[原]无脑操作:IDEA + maven + Shiro + SpringBoot + JPA + Thymeleaf实现基础认证权限>介绍了实现Shiro的基础认证.本篇谈谈实现 ...

  4. 【原】无脑操作:IDEA + maven + Shiro + SpringBoot + JPA + Thymeleaf实现基础认证权限

    开发环境搭建参见<[原]无脑操作:IDEA + maven + SpringBoot + JPA + Thymeleaf实现CRUD及分页> 需求: ① 除了登录页面,在地址栏直接访问其他 ...

  5. 【原】无脑操作:eclipse + maven搭建SSM框架

    网上看到一些Spring + Spring MVC + MyBatis框架的搭建教程,不是很详细或是时间久远了,自己动手整一个简单无脑的! 0.系统环境 1)Windows 10 企业版 2)JDK ...

  6. 【原】无脑操作:ElasticSearch学习笔记(01)

    开篇来自于经典的“保安的哲学三问”(你是谁,在哪儿,要干嘛) 问题一.ElasticSearch是什么?有什么用处? 答:截至2018年12月28日,从ElasticSearch官网(https:// ...

  7. 【原】无脑操作:IDEA + maven + SpringBoot + JPA + EasyUI实现CRUD及分页

    背景:上一篇文章的界面太丑.没有条件查询功能.所以做一些改进,整合EasyUI做实现.(仅以此文纪念表格中出现的这些朋友工作六周年,祭奠一下逝去的青春^_^) 一.开发环境(参照上一篇文章) 补充:E ...

  8. 【原】无脑操作:Windows 10 + MySQL 5.5 安装使用及免安装使用

    本文介绍Windows 10环境下, MySQL 5.5的安装使用及免安装使用 资源下载: MySQL安装文件:http://download.csdn.net/detail/lf19820717/9 ...

  9. 【原】无脑操作:IDEA + maven + SpringBoot + JPA + Thymeleaf实现CRUD及分页

    一.开发环境: 1.windows 7 企业版 2.IDEA 14 3.JDK 1.8 4.Maven 3.5.2 5.MariaDB 6.SQLYog 二.Maven设置: Maven目录下的con ...

随机推荐

  1. Restframe_work 回顾记忆集

    目录 Restframe_work 回顾记忆集 rest_framework主要功能介绍 rest_framework主要模块介绍 记忆集 错题集 混淆集 重点集 难点集 Restframe_work ...

  2. 关于页面传参,decodeURI和decodeURIComponent

    之前写过一个关于页面传参的,但是是前端相对于自己的页面做的跳转,也就是页面1,跳转到页面2,里面带的参数.这里可以参考我上一篇文章,包括里面参数中如果有数组和json格式的情况.但是需要注意的是,我前 ...

  3. gitbook 入门教程之使用 gitbook-editor 编辑器开发电子书

    亲测,目前已不再支持旧版 gitbook-editor 编辑器,而官网也没有相应的新版编辑器,如果哪位找到了新版编辑器,还望告知! 现在注册 gitbook 账号会默认重定向到 新版官网,而 旧版官网 ...

  4. iTop软件功能分析以及优缺点比较

    iTop软件功能分析以及优缺点比较 iTop对标文档 1. 概述 2. CMDB 3. 主要功能模块 3.1 配置管理(Configuration Managment) 3.2 用户请求管理(Help ...

  5. JetBrains 系列编译器 破解(idea,webstrom ,pycharm等)

    第一步: 下载安装好Idea 或者Pychar ,安装好后不可运行 第二步: 安装完成之后不要立即运行,以下提供JetbrainsCrack的jar包来破解: jar包资源自行百度 下载之后,把Jet ...

  6. Windows Server 2016-Windows 时间服务概览

    同步 Windows 时间服务 (W32Time) 的日期和时间的所有运行 Active Directory 域服务 (AD DS) 的计算机. 时间同步至关重要的许多 Windows 服务和的业务线 ...

  7. Linux 桌面玩家指南:13. 使用 Git 及其和 Eclipse 的集成

    特别说明:要在我的随笔后写评论的小伙伴们请注意了,我的博客开启了 MathJax 数学公式支持,MathJax 使用$标记数学公式的开始和结束.如果某条评论中出现了两个$,MathJax 会将两个$之 ...

  8. 一些关于IO流的问题

    一:知识点 二:代码 1.阅读下面程序段: BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream(&quo ...

  9. python --- 插入排序算法

    先上一张图,看看能不能从里面悟出些什么: 问题的解决思路: 就是当插入第i个的时候,前面的[i- 1]个已经排好了,这时候lst[i]就倒过来逐个和前面的关键字顺序进行比较,找到插入位置即将lst[i ...

  10. .NET Core TDD 前传: 编写易于测试的代码 -- 全局状态

    第1篇: 讲述了如何创造"缝".  "缝"(seam)是需要知道的概念. 第2篇, 避免在构建对象时写出不易测试的代码. 第3篇, 依赖项和迪米特法则. 本文是 ...