285
社区成员




The Link Your Class | https://bbs.csdn.net/forums/MUEE308FZU202201 |
The Link of Requirement of This Assignment | https://bbs.csdn.net/topics/608859318 |
MU STU ID and FZU STU ID | FZU ID : 832001124 MU ID : 20124732 |
Teammate's MU STU ID and FZU STU ID | MU ID : 20123108 20122292 FZU ID :832001302 832001321 |
Teammate's blog Link | |
GitHub Link | https://github.com/fish-Rita/bobing/tree/master |
Video demo Link | https://www.bilibili.com/video/BV1gd4y1b7Hq |
Online Game Link | http://47.122.44.9:5678/ |
4.Key functions & Programming Thinking
5.Thing Take Long Time to Finish
6.GitHub Link and Commit Record
7.Program Experience Great Gain
PSP | ESTIMATE TIME(MINUTE) | ESTIMATE TIME(MINUTE) |
Planning | 45 | 30 |
Estimate | 5 | 5 |
Development | 30 | 50 |
Analysis | 60 | 70 |
Design Spec | 10 | 10 |
Design Review | 0 | 0 |
Coding Standard | 20 | 15 |
Design | 40 | 60 |
Coding | 240 | 300 |
Code Review | 10 | 15 |
Test | 60 | 80 |
Reporting | \ | \ |
Test Report | 10 | 20 |
Size Measurement | 10 | 10 |
Postmortem & Process Improvement Plan | 20 | 50 |
Total | 560 | 715 |
Time(Week 11) | New Coding Line | Accumulated Elapsed Time(mins) | What we have done |
---|---|---|---|
1 | 0 | 480 | Learn the css and html language individually |
2 | 100 | 840 |
Learning the basis of python flusk to arrange back end |
3 | 300 | 1260 | Start to write the function of logging and registering |
4 | 500 | 1800 | Use js language to write the judement of resuls of dices in various modes and finish writing the front end |
5 | 100 | 2160 | Test the code and upload it to the Aliyun server |
6 | 780 | 2520 | Record App video and final test our program |
The video demonstration of our software applet has already uploaded on bilibili and the Link is:
Online game link is:
There are some worth mentioning points are as follows 😛😜😝:
4.1 Deal with back end programs to achieve login and register
We use python flask to reach the register and login function, and verify whether the information menu submitted by the user is legal or not, if it can not meet the specifications and requirements, it will be intercepted 👇.
class LoginForm(FlaskForm):
"""登录表单类"""
username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
class RegisterForm(FlaskForm):
email = StringField("Email", validators=[DataRequired(), Length(1, 64)])
username = StringField(
"Username",
validators=[
DataRequired(),
Length(1, 64),
Regexp(
"^[A-Za-z][A-Za-z0-9_.]*$",
0,
"Usernames must have only letters, " "numbers, dots or underscores",
),
],
)
password = PasswordField(
"Password",
validators=[
DataRequired(),
EqualTo("password_confirmation", message="Passwords must match."),
],
)
password_confirmation = PasswordField("Confirm password", validators=[DataRequired()])
submit = SubmitField(label="Register")
Once the user finish registering, we start to deal with the user information. Initially, we use the method of Cryptographic Hash Function to encrypt the user information and store it into the database. When the user finish logging, the password submitted by the user will be compared with the exsisting hashed passwords. Then we make session to record the user message 👇.
@app.route('/login', methods=['GET', 'POST']) # 登录
def login():
form = LoginForm()
if request.method == 'GET':
return render_template('login.html', form=form)
user_name = form.username.data
password = form.password.data
user_info = get_user(user_name) # 从用户数据中查找用户记录
if user_info is None:
emsg = "please enter username or password"
return render_template('login.html', err=emsg)
else:
user = User(user_info[0]) # 创建用户实体
if check_password_hash(user.password_hash, password): # 校验密码
login_user(user)
return redirect(url_for('index'))
else:
emsg = "username or password error!"
return render_template('login.html', err=emsg)
@app.route("/register", methods=["GET", "POST"])
def register():
if request.method == 'GET':
return render_template('register.html')
form = RegisterForm()
if not form.username.data or not form.password.data or not form.email.data:
emsg = "please enter the message"
return render_template('register.html', err=emsg)
sql = "insert into users(username, password, email, money) " \
"VALUES ('%s', '%s', '%s', '%d')" % \
(form.username.data, generate_password_hash(form.password.data), form.email.data, 0)
try:
cursor.execute(sql)
conf.db.commit()
except pymysql.err.InterfaceError as e:
print(e, type(e))
conf.db.ping(True)
except AttributeError:
conf.e()
logging.error(AttributeError)
return redirect(url_for('login'))
4.2.Achieving the function of different game modes
For this part, we designed an algorithm based on the game rules to calculate the player's score and used ajax to dynamically send the data from the front end to the back end. Then, we store it into the database 👇.
Single player:
@app.route('/individual', methods=['GET'])
@login_required
def individual():
get_point = request.args.get('point')
sql = f"select money from users where username = '{current_user.username}'"
try:
cursor.execute(sql)
conf.db.commit()
result = cursor.fetchall()
if result:
plus = result[0][0] + int(get_point)
sql_update = f"update users set money = '{plus}' where username = '{current_user.username}'"
cursor.execute(sql_update)
conf.db.commit()
except pymysql.err.InterfaceError as e:
print(e, type(e))
conf.db.ping(True)
except Exception as e:
conf.e()
logging.error(e)
return render_template('individual.html')
Multiple playes:
// 掷骰子的功能
function rollTheDice() {
setTimeout(function () {
if (document.getElementById("b1").innerText === "Open") {
open()
} else {
for (var i=0; i<2; i++) {
if (points[i] === -1) {
clear()
stop(i)
break
}
}
if (points[points.length-1] !== -1) {
if (points[0]===points[1]) {
document.querySelector("h3").innerHTML = "draw!"
} else {
points[0] > points[1] ?
document.querySelector("h3").innerHTML = "player 1 win!" :
document.querySelector("h3").innerHTML = "player 2 win!"
}
points=[-1,-1]}
}
},1000)
}
4.3 Design the ranking list based on history records
The usernames and scores of the top five users No.1-No.5 are sorted by MySQL and then we connect it to the front end page 👇.
@app.route('/ranking', methods=['GET'])
@login_required
def ranking():
sql = "select username, money from users order by money desc limit 5"
try:
cursor.execute(sql)
conf.db.commit()
result = cursor.fetchall()
except pymysql.err.InterfaceError as e:
print(e, type(e))
conf.db.ping(True)
return render_template('test.html')
except Exception as e:
conf.e()
logging.error(e)
return render_template('test.html')
if len(result) >= 5:
return render_template('ranking.html',
u1=result[0][0], m1=result[0][1],
u2=result[1][0], m2=result[1][1],
u3=result[2][0], m3=result[2][1],
u4=result[3][0], m4=result[3][1],
u5=result[4][0], m5=result[4][1]
)
else:
return render_template('test.html')
This is a basic user class that inherits the accumulation of users from the flask login middleware and contains the basic attributes of the users 👇.
class User(UserMixin):
"""用户类"""
def __init__(self, user):
self.username = user[1]
self.password_hash = user[2]
self.id = user[0]
def verify_password(self, password):
"""密码验证"""
if self.password_hash is None:
return False
return self.password_hash == password
def get_id(self):
"""获取用户ID"""
return self.id
@staticmethod
def get(user_id):
"""根据用户ID获取用户实体,为 login_user 方法提供支持"""
if not user_id:
return None
sql = f'select * from users where id = {user_id}'
try:
cursor.execute(sql)
conf.db.commit()
result = cursor.fetchall()
for user in result:
if user[0] == user_id:
return User(user)
return None
except Exception as e:
conf.e()
print(e)
4.4 Upload the applet into the Aliyun server
We configure database information to connect the application to the MySQL database, and then we use docker to arrange them to the server 👇.
import yaml
import os
import pymysql
filePath = os.path.dirname(__file__)
fileNamePath = os.path.split(os.path.realpath(__file__))[0]
yamlPath = os.path.join(fileNamePath, 'config.yaml')
f = open(yamlPath, 'r', encoding='utf-8')
cont = f.read()
x = yaml.load(cont, Loader=yaml.FullLoader)
db = pymysql.connect(
host=x['DB']['host'],
user=x['DB']['username'],
password=str(x['DB']['password']),
port=x['DB']['port'],
database=x['DB']['database']
)
Docker can be used to arrange the server 👇.
FROM python:3.9
ADD . /app
WORKDIR /app
RUN pip install -r requirements.txt
RUN pip3 install cryptography -i https://pypi.tuna.tsinghua.edu.cn/simple
CMD ["python", "app.py"]
As the saying goes: All things are difficult before they are easy. Since we had never come into contact with HTML, CSS, Javascript and other technologies, and also forgot the python we learned in the freshman year, we spent a lot of time at the beginning watching relevant videos on platforms like Bilibili and CSDN, reading related blog materials, mastering some basic knowledge and having a general understanding of the technology. And then learn other advanced knowledge as needed during the implementation of the function.
In the process of software practice, especially the setting of the logic of the game is relatively difficult. Sometimes there are some errors that need to be modified, and sometimes it takes a lot of time to find the errors.
We used a server we had before, but we didn't know why it couldn't access the IP. We searched a lot of information and made a lot of attempts but couldn't access the IP. Then we bought a new server and still didn't solve the problem.
When we finish a version, we find problems that need to be fixed, and then we make suggestions to improve the game interface and the game experience, which sometimes requires rework and takes a lot of time.
For convenience, we share the same computer to write most of the codes for convenience thus all of our work has been uploaded to the same github.
Actually, we stayed up a few nights and even consumed some kinds of junk food as supply of body energy hhh~ For us, although it was a really hard process, we learned a lot basic and common grammar usages on developing the applets, which also make us realize the vital importance of communication and cooperation with partners, eventually, we achieve a sense of achievement.
The level of difficulty in this lab is not friendly for us due to the limitation of time and specialized master of software development. Luckily, since one of our teammates is more familiar with using flask structure, we use it as a tool to develop web service. Meanwhile, for front end, we know more about how to use html and css language, that we never deal with before, to properly arrange a applet web page and use javascript to judge the results of dices; for back end, we use python to check the information of logging and store the account’s data. Furthermore, we successfully package all the program and deliver it to the Aliyun sever. Despite there are a lot of features we haven't implemented yet, we still propose some plans for out further improvement if we had enough time such as improvements of multiplayer interface’s and optimization of the game experience and set up BGM, etc.