commit 1d3f6a47a8182bb04e823bb57157a5d1dea121e1 Author: yanbo2020 Date: Wed Jun 1 19:01:54 2022 +0800 bug209-yaaqob diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..413c71c --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +.idea/ +venv/ +app/__init__.py +app/__pycache__/ +app/sqlite_commands.py +app/static/usr/*.jpg +app/static/img/ +app/static/frequency/frequency_*.pickle +app/static/frequency/frequency.p +app/static/wordfreqapp.db +app/static/donate-the-author.jpg +app/static/donate-the-author-hidden.jpg diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..284195a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,4 @@ +FROM tiangolo/uwsgi-nginx-flask:python3.6 +COPY requirements.txt /app +RUN pip3 install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/ +COPY ./app /app diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..2633859 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,41 @@ +pipeline { + agent any + + triggers { + + pollSCM('') // Enabling being build on Push + + } + + stages { + stage('MakeDatabasefile') { + steps { + sh 'touch ./app/static/wordfreqapp.db && rm -f ./app/static/wordfreqapp.db' + sh 'cat ./app/static/wordfreqapp.sql | sqlite3 ./app/static/wordfreqapp.db' + } + } + stage('BuildIt') { + steps { + echo 'Building..' + sh 'sudo docker kill $(sudo docker ps -q)' + sh 'sudo docker build -t englishpal .' + sh 'sudo docker run -d -p 91:80 -v /var/lib/jenkins/workspace/EnglishPal_Pipeline_master/app/static/frequency:/app/static/frequency -t englishpal' + } + } + stage('TestIt') { + steps { + echo 'Testing..' + sh 'sudo docker run -d -p 4444:4444 selenium/standalone-firefox' + sh 'pip3 install pytest -U -q' + sh 'pip3 install pytest-html -U -q' + sh 'pip3 install selenium -U -q' + sh 'pytest -v -s --html=EnglishPalTestReport.html ./app/test' + } + } + stage('DeployIt') { + steps { + echo 'Deploying (TBD)' + } + } + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..ec92598 --- /dev/null +++ b/README.md @@ -0,0 +1,184 @@ +# EnglishPal - Learn English Words Smartly + + + +Hui Lan + +1 November 2019 + + +## What is it? + + +EnglishPal allows the user to build his list of new English words +picked from articles selected for him according his vocabulary level. + + +## Run it on a local machine + + +`python3 main.py` + +Make sure you have the SQLite database file in `app/static` (see below). + + +## Run it as a Docker container + + +Assuming that docker has been installed and that you are a sudo user (i.e., sudoer), start the program by typing the following command in directory `EnglishPal`: + +`sudo ./build.sh` + +Open your favourite Internet browser and enter this URL address: `http://ip-address:90`. + +### Explanation on the commands in build.sh + +My steps for deploying English on the server. + +- ssh to ubuntu@118.*.*.118 + +- cd to /home/lanhui/englishpal2/EnglishPal + +- Stop all docker service: `sudo service docker restart`. If you know the docker container ID, then the above command is an overkill. Use the following command instead: `sudo docker stop ContainerID`. You could get all container IDs with the following command: `sudo docker ps` + +- Rebuild container. Run the following command to rebuild a docker image after the code gets updated: `sudo docker build -t englishpal .` + +- Run the application: `sudo docker run -d -p 90:80 -v /home/lanhui/englishpal2/EnglishPal/app/static/frequency:/app/static/frequency -t englishpal`. If you use `sudo docker run -d -p 90:80 -t englishpal`, data will be lost after terminating the program. + +- Save space: `sudo docker system prune -a -f` + + +### Other useful docker commands + +- `sudo docker ps -a` + +- `sudo docker logs image_name`, where image_name could be obtained from `sudo docker ps`. + +`build.sh` contains all the above commands. Run "sudo ./build.sh" to rebuild and run the web application. + + + +## Importing articles + + +All articles are stored in the `article` table in a SQLite file called +`app/static/wordfreqapp.db`. + +### Adding new articles + +To add articles, open and edit `app/static/wordfreqapp.db` using DB Browser for SQLite (https://sqlitebrowser.org). + +### Exporting the database + +Export wordfreqapp.db to wordfreqapp.sql using the following commands: + +- sqlite3 wordfreqapp.db + +- .output wordfreqapp.sql + +- .dump + +- .exit + +Put wordfreqapp.sql (not wordfreqapp.db) under version control. + +### Creating SQLite file from wordfreqapp.sql + + +Create wordfreqapp.db using this command: `cat wordfreqapp.sql | +sqlite3 wordfreqapp.db`. Delete wordfreqapp.db first if it exists. + + +### Uploading wordfreqapp.db to the server + + +`pscp wordfreqapp.db lanhui@118.*.*.118:/home/lanhui/englishpal/app/static` + + + +## Feedback + +We welcome feedback on EnglishPal. + +### Respondent 1 + + +"Need a phone app. I use phone a lot. You cannot ask students to use computers." + +Can take a picture for text. Automatic translation. + +### Respondent 2 + + +“成为会员”改成“注册” + +“登出”改成“退出” + +“收集生词吧”改成“生词收集栏” + +“不要自动显示下一篇” + +需要有“上一篇”、“下一篇” + + + +## Bug tracking + + +EnglishPal's bugs and improvement suggestions are recorded in [Bugzilla](http://118.25.96.118/bugzilla/buglist.cgi?bug_status=__all__&list_id=1302&order=Importance&product=EnglishPal&query_format=specific). Send (lanhui at zjnu.edu.cn) an email message for opening a Bugzilla account or reporting a bug. + + + +## TODO + + +- Fix Bug: Internal server error when register using an email address. + +- Usability testing + + +## Improvements made by contributors + + +### 朱文绮 + + +在生词簿每个单词后面,加上两个按钮,熟悉与不熟悉: + +- 如果点熟悉,就将生词簿中该单词后面记录的添加次数减一,直至减为0,就将该单词从生词簿中移除。 + +- 如果点不熟悉,就将生词簿中该单词后面记录的添加次数加一。 + +### 李康恬 + + +Add the function of "Delete already known and well-known words from +the words' library", on the one hand, it can conform to the usage +habits of some users, who do not like that their words' libraries have +too many words that they already know, on the other hand, it can +reduce unnecessary memory occupied by the database, in addition, it +can also improve the simplicity of the page. + +More information at: http://118.25.96.118/kanboard/?controller=TaskViewController&action=readonly&task_id=736&token=81a561da57ff7a172da17a480f0d421ff3bc69efbd29437daef90b1b8959 + + +### 占健豪 + + +Click the Familiar or Unfamiliar button (current word frequency>1), the current word position is displayed at the top of the page; + +Click the Familiar or Unfamiliar button (current word frequency is 1), and the page will be displayed as the top of the entire page. + +Demo video link: https://b23.tv/QuB77m + +### 张小飞 + + +修复了以下漏洞。 + +漏洞:用 `‘ or ‘1’=‘1’` 这段字符可以作为任何账号的密码登录。 + +Bug report: http://118.25.96.118/bugzilla/show_bug.cgi?id=215 + + +*Last modified on 2021-10-17* \ No newline at end of file diff --git a/app/Article.py b/app/Article.py new file mode 100644 index 0000000..774d25a --- /dev/null +++ b/app/Article.py @@ -0,0 +1,136 @@ +from WordFreq import WordFreq +from wordfreqCMD import youdao_link, sort_in_descending_order +from UseSqlite import InsertQuery, RecordQuery +import pickle_idea, pickle_idea2 +import os +import random, glob +import hashlib +from datetime import datetime +from flask import Flask, request, redirect, render_template, url_for, session, abort, flash, get_flashed_messages +from difficulty import get_difficulty_level, text_difficulty_level, user_difficulty_level + + +path_prefix = '/var/www/wordfreq/wordfreq/' +path_prefix = './' # comment this line in deployment + + +def total_number_of_essays(): + rq = RecordQuery(path_prefix + 'static/wordfreqapp.db') + rq.instructions("SELECT * FROM article") + rq.do() + result = rq.get_results() + return len(result) + + +def get_article_title(s): + return s.split('\n')[0] + + +def get_article_body(s): + lst = s.split('\n') + lst.pop(0) # remove the first line + return '\n'.join(lst) + + +def get_today_article(user_word_list, articleID): + rq = RecordQuery(path_prefix + 'static/wordfreqapp.db') + if articleID == None: + rq.instructions("SELECT * FROM article") + else: + rq.instructions('SELECT * FROM article WHERE article_id=%d' % (articleID)) + rq.do() + result = rq.get_results() + random.shuffle(result) + + # Choose article according to reader's level + d1 = load_freq_history(path_prefix + 'static/frequency/frequency.p') + d2 = load_freq_history(path_prefix + 'static/words_and_tests.p') + d3 = get_difficulty_level(d1, d2) + + d = {} + d_user = load_freq_history(user_word_list) + user_level = user_difficulty_level(d_user, d3) # more consideration as user's behaviour is dynamic. Time factor should be considered. + random.shuffle(result) # shuffle list + d = random.choice(result) + text_level = text_difficulty_level(d['text'], d3) + if articleID == None: + for reading in result: + text_level = text_difficulty_level(reading['text'], d3) + factor = random.gauss(0.8, + 0.1) # a number drawn from Gaussian distribution with a mean of 0.8 and a stand deviation of 1 + if within_range(text_level, user_level, (8.0 - user_level) * factor): + d = reading + break + + s = '' % ( + user_level, text_level) + s += '

Article added on: %s

' % (d['date']) + s += '
' + article_title = get_article_title(d['text']) + article_body = get_article_body(d['text']) + s += '

%s

' % (article_title) + s += '

%s

' % (article_body) + s += '

%s

' % (d['source']) + s += '

%s

' % (get_question_part(d['question'])) + s = s.replace('\n', '
') + s += '%s' % (get_answer_part(d['question'])) + s += '
' + session['articleID'] = d['article_id'] + return s + + +def load_freq_history(path): + d = {} + if os.path.exists(path): + d = pickle_idea.load_record(path) + return d + + +def within_range(x, y, r): + return x > y and abs(x - y) <= r + + +def get_question_part(s): + s = s.strip() + result = [] + flag = 0 + for line in s.split('\n'): + line = line.strip() + if line == 'QUESTION': + result.append(line) + flag = 1 + elif line == 'ANSWER': + flag = 0 + elif flag == 1: + result.append(line) + return '\n'.join(result) + + +def get_answer_part(s): + s = s.strip() + result = [] + flag = 0 + for line in s.split('\n'): + line = line.strip() + if line == 'ANSWER': + flag = 1 + elif flag == 1: + result.append(line) + # https://css-tricks.com/snippets/javascript/showhide-element/ + js = ''' + + ''' + html_code = js + html_code += '\n' + html_code += '\n' + html_code += '\n' % ('\n'.join(result)) + return html_code \ No newline at end of file diff --git a/app/Login.py b/app/Login.py new file mode 100644 index 0000000..65047f7 --- /dev/null +++ b/app/Login.py @@ -0,0 +1,77 @@ +import hashlib +from datetime import datetime +from UseSqlite import InsertQuery, RecordQuery + +path_prefix = '/var/www/wordfreq/wordfreq/' +path_prefix = './' # comment this line in deployment + + +def verify_user(username, password): + rq = RecordQuery(path_prefix + 'static/wordfreqapp.db') + password = md5(username + password) + rq.instructions_with_parameters("SELECT * FROM user WHERE name=:username AND password=:password", dict( + username=username, password=password)) # the named style https://docs.python.org/3/library/sqlite3.html + rq.do_with_parameters() + result = rq.get_results() + return result != [] + + +def add_user(username, password): + start_date = datetime.now().strftime('%Y%m%d') + expiry_date = '20221230' + # 将用户名和密码一起加密,以免暴露不同用户的相同密码 + password = md5(username + password) + rq = InsertQuery(path_prefix + 'static/wordfreqapp.db') + rq.instructions_with_parameters("INSERT INTO user VALUES (:username, :password, :start_date, :expiry_date)", dict( + username=username, password=password, start_date=start_date, expiry_date=expiry_date)) + rq.do_with_parameters() + + +def check_username_availability(username): + rq = RecordQuery(path_prefix + 'static/wordfreqapp.db') + rq.instructions_with_parameters( + "SELECT * FROM user WHERE name=:username", dict(username=username)) + rq.do_with_parameters() + result = rq.get_results() + return result == [] + + +def change_password(username, old_password, new_password): + ''' + 修改密码 + :param username: 用户名 + :param old_password: 旧的密码 + :param new_password: 新密码 + :return: 修改成功:True 否则:False + ''' + if not verify_user(username, old_password): # 旧密码错误 + return False + # 将用户名和密码一起加密,以免暴露不同用户的相同密码 + password = md5(username + new_password) + rq = InsertQuery(path_prefix + 'static/wordfreqapp.db') + rq.instructions_with_parameters("UPDATE user SET password=:password WHERE name=:username", dict( + password=password, username=username)) + rq.do_with_parameters() + return True + + +def get_expiry_date(username): + rq = RecordQuery(path_prefix + 'static/wordfreqapp.db') + rq.instructions_with_parameters( + "SELECT expiry_date FROM user WHERE name=:username", dict(username=username)) + rq.do_with_parameters() + result = rq.get_results() + if len(result) > 0: + return result[0]['expiry_date'] + else: + return '20191024' + + +def md5(s): + ''' + MD5摘要 + :param str: 字符串 + :return: 经MD5以后的字符串 + ''' + h = hashlib.md5(s.encode(encoding='utf-8')) + return h.hexdigest() diff --git a/app/UseSqlite.py b/app/UseSqlite.py new file mode 100644 index 0000000..ea4baeb --- /dev/null +++ b/app/UseSqlite.py @@ -0,0 +1,87 @@ +########################################################################### +# Copyright 2019 (C) Hui Lan +# Written permission must be obtained from the author for commercial uses. +########################################################################### + + +# Reference: Dusty Phillips. Python 3 Objected-oriented Programming Second Edition. Pages 326-328. +# Copyright (C) 2019 Hui Lan + +import sqlite3 + +class Sqlite3Template: + def __init__(self, db_fname): + self.db_fname = db_fname + + def connect(self, db_fname): + self.conn = sqlite3.connect(self.db_fname) + + def instructions(self, query_statement): + raise NotImplementedError() + + def operate(self): + self.conn.row_factory = sqlite3.Row + self.results = self.conn.execute(self.query) # self.query is to be given in the child classes + self.conn.commit() + + def format_results(self): + raise NotImplementedError() + + def do(self): + self.connect(self.db_fname) + self.instructions(self.query) + self.operate() + + def instructions_with_parameters(self, query_statement, parameters): + self.query = query_statement + self.parameters = parameters + + def do_with_parameters(self): + self.connect(self.db_fname) + self.instructions_with_parameters(self.query, self.parameters) + self.operate_with_parameters() + + def operate_with_parameters(self): + self.conn.row_factory = sqlite3.Row + self.results = self.conn.execute(self.query, self.parameters) # self.query is to be given in the child classes + self.conn.commit() + + +class InsertQuery(Sqlite3Template): + def instructions(self, query): + self.query = query + + +class RecordQuery(Sqlite3Template): + def instructions(self, query): + self.query = query + + def format_results(self): + output = [] + for row_dict in self.results.fetchall(): + lst = [] + for k in dict(row_dict): + lst.append( row_dict[k] ) + output.append(', '.join(lst)) + return '\n\n'.join(output) + + def get_results(self): + result = [] + for row_dict in self.results.fetchall(): + result.append( dict(row_dict) ) + return result + + + +if __name__ == '__main__': + + #iq = InsertQuery('RiskDB.db') + #iq.instructions("INSERT INTO inspection Values ('FoodSupplies', 'RI2019051301', '2019-05-13', '{}')") + #iq.do() + #iq.instructions("INSERT INTO inspection Values ('CarSupplies', 'RI2019051302', '2019-05-13', '{[{\"risk_name\":\"elevator\"}]}')") + #iq.do() + + rq = RecordQuery('wordfreqapp.db') + rq.instructions("SELECT * FROM article WHERE level=3") + rq.do() + #print(rq.format_results()) diff --git a/app/WordFreq.py b/app/WordFreq.py new file mode 100644 index 0000000..3620a41 --- /dev/null +++ b/app/WordFreq.py @@ -0,0 +1,25 @@ +########################################################################### +# Copyright 2019 (C) Hui Lan +# Written permission must be obtained from the author for commercial uses. +########################################################################### + +from wordfreqCMD import remove_punctuation, freq, sort_in_descending_order +import string + +class WordFreq: + def __init__(self, s): + self.s = remove_punctuation(s) + + def get_freq(self): + lst = [] + for t in freq(self.s): + word = t[0] + if len(word) > 0 and word[0] in string.ascii_letters: + lst.append(t) + return sort_in_descending_order(lst) + + +if __name__ == '__main__': + f = WordFreq('BANANA; Banana, apple ORANGE Banana banana.') + print(f.get_freq()) + diff --git a/app/Yaml.py b/app/Yaml.py new file mode 100644 index 0000000..00974aa --- /dev/null +++ b/app/Yaml.py @@ -0,0 +1,27 @@ +''' +Yaml.py +配置文件包括: + ./static/config.yml + ./layout/partial/header.html + ./layout/partial/footer.html +''' +import yaml as YAML +import os + +path_prefix = './' # comment this line in deployment + +# YAML文件路径 +ymlPath = path_prefix + 'static/config.yml' + +# partial文件夹路径 +partialPath = path_prefix + 'layout/partial/' +f = open(ymlPath, 'r', encoding='utf-8') # 以'UTF-8'格式打开YAML文件 +cont = f.read() # 以文本形式读取YAML + +yml = YAML.load(cont, Loader=YAML.FullLoader) # 加载YAML + +with open(partialPath + 'header.html', 'r', encoding='utf-8') as f: + yml['header'] = f.read() # header内的文本会被直接添加到所有页面的head标签内 + +with open(partialPath + 'footer.html', 'r', encoding='utf-8') as f: + yml['footer'] = f.read() # footer内的文本会被直接添加到所有页面的最底部 diff --git a/app/account_service.py b/app/account_service.py new file mode 100644 index 0000000..753c51e --- /dev/null +++ b/app/account_service.py @@ -0,0 +1,129 @@ +from flask import * +from Login import check_username_availability, verify_user, add_user, get_expiry_date, change_password + +# 初始化蓝图 +accountService = Blueprint("accountService", __name__) + + +### Sign-up, login, logout ### +@accountService.route("/signup", methods=['GET', 'POST']) +def signup(): + ''' + 注册 + :return: 根据注册是否成功返回不同界面 + ''' + if request.method == 'GET': + # GET方法直接返回注册页面 + return render_template('signup.html') + elif request.method == 'POST': + # POST方法需判断是否注册成功,再根据结果返回不同的内容 + username = escape(request.form['username']) + password = escape(request.form['password']) + + available = check_username_availability(username) + if not available: # 用户名不可用 + flash('用户名 %s 已经被注册。' % (username)) + return render_template('signup.html') + elif len(password.strip()) < 4: # 密码过短 + return '密码过于简单。' + else: # 添加账户信息 + add_user(username, password) + verified = verify_user(username, password) + if verified: + # 写入session + session['logged_in'] = True + session[username] = username + session['username'] = username + session['expiry_date'] = get_expiry_date(username) + session['articleID'] = None + return '

恭喜,你已成功注册, 你的用户名是 %s

\ +

开始使用 返回首页

' % (username, username, username) + else: + return '用户名密码验证失败。' + + +@accountService.route("/login", methods=['GET', 'POST']) +def login(): + ''' + 登录 + :return: 根据登录是否成功返回不同页面 + ''' + if request.method == 'GET': + # GET请求 + if not session.get('logged_in'): + # 未登录,返回登录页面 + return render_template('login.html') + else: + # 已登录,提示信息并显示登出按钮 + return '你已登录 %s。 登出点击这里。' % ( + session['username'], session['username']) + elif request.method == 'POST': + # POST方法用于判断登录是否成功 + # check database and verify user + username = escape(request.form['username']) + password = escape(request.form['password']) + verified = verify_user(username, password) + if verified: + # 登录成功,写入session + session['logged_in'] = True + session[username] = username + session['username'] = username + user_expiry_date = get_expiry_date(username) + session['expiry_date'] = user_expiry_date + session['articleID'] = None + return redirect(url_for('user_bp.userpage', username=username)) + else: + return '无法通过验证。' + + +@accountService.route("/logout", methods=['GET', 'POST']) +def logout(): + ''' + 登出 + :return: 重定位到主界面 + ''' + # 将session标记为登出状态 + session['logged_in'] = False + return redirect(url_for('mainpage')) + + +@accountService.route("/reset", methods=['GET', 'POST']) +def reset(): + ''' + 重设密码 + :return: 返回适当的页面 + ''' + # 下列方法用于防止未登录状态下的修改密码 + if not session.get('logged_in'): + return render_template('login.html') + username = session['username'] + if username == '': + return redirect('/login') + if request.method == 'GET': + # GET请求返回修改密码页面 + return render_template('reset.html', username=session['username'], state='wait') + else: + # POST请求用于提交修改后信息 + old_password = escape(request.form['old-password']) + new_password = escape(request.form['new-password']) + flag = change_password(username, old_password, new_password) # flag表示是否修改成功 + if flag: + session['logged_in'] = False + return \ +''' + + +''' + + else: + return \ +''' + + +''' \ No newline at end of file diff --git a/app/difficulty.py b/app/difficulty.py new file mode 100644 index 0000000..50aa179 --- /dev/null +++ b/app/difficulty.py @@ -0,0 +1,249 @@ +########################################################################### +# Copyright 2019 (C) Hui Lan +# Written permission must be obtained from the author for commercial uses. +########################################################################### + +# Purpose: compute difficulty level of a English text + +import pickle +import math +from wordfreqCMD import remove_punctuation, freq, sort_in_descending_order, sort_in_ascending_order + + +def load_record(pickle_fname): + f = open(pickle_fname, 'rb') + d = pickle.load(f) + f.close() + return d + + +def difficulty_level_from_frequency(word, d): + level = 1 + if not word in d: + return level + + if 'what' in d: + ratio = (d['what']+1)/(d[word]+1) # what is a frequent word + level = math.log( max(ratio, 1), 2) + + level = min(level, 8) + return level + + +def get_difficulty_level(d1, d2): + d = {} + L = list(d1.keys()) # in d1, we have freuqence for each word + L2 = list(d2.keys()) # in d2, we have test types (e.g., CET4,CET6,BBC) for each word + L.extend(L2) + L3 = list(set(L)) # L3 contains all words + for k in L3: + if k in d2: + if 'CET4' in d2[k]: + d[k] = 4 # CET4 word has level 4 + elif 'CET6' in d2[k]: + d[k] = 6 + elif 'BBC' in d2[k]: + d[k] = 8 + if k in d1: # BBC could contain easy words that are not in CET4 or CET6. So 4 is not reasonable. Recompute difficulty level. + d[k] = min(difficulty_level_from_frequency(k, d1), d[k]) + elif k in d1: + d[k] = difficulty_level_from_frequency(k, d1) + + return d + + + +def revert_dict(d): + ''' + In d, word is the key, and value is a list of dates. + In d2 (the returned value of this function), time is the key, and the value is a list of words picked at that time. + ''' + d2 = {} + for k in d: + if type(d[k]) is list: # d[k] is a list of dates. + lst = d[k] + elif type(d[k]) is int: # for backward compatibility. d was sth like {'word':1}. The value d[k] is not a list of dates, but a number representing how frequent this word had been added to the new word book. + freq = d[k] + lst = freq*['2021082019'] # why choose this date? No particular reasons. I fix the bug in this date. + + for time_info in lst: + date = time_info[:10] # until hour + if not date in d2: + d2[date] = [k] + else: + d2[date].append(k) + return d2 + + +def user_difficulty_level(d_user, d): + d_user2 = revert_dict(d_user) # key is date, and value is a list of words added in that date + count = 0 + geometric = 1 + for date in sorted(d_user2.keys(), reverse=True): # most recently added words are more important while determining user's level + lst = d_user2[date] # a list of words + lst2 = [] # a list of tuples, (word, difficulty level) + for word in lst: + if word in d: + lst2.append((word, d[word])) + + lst3 = sort_in_ascending_order(lst2) # easiest tuple first + #print(lst3) + for t in lst3: + word = t[0] + hard = t[1] + #print('WORD %s HARD %4.2f' % (word, hard)) + geometric = geometric * (hard) + count += 1 + if count >= 10: + return geometric**(1/count) + + return geometric**(1/max(count,1)) + + +def text_difficulty_level(s, d): + s = remove_punctuation(s) + L = freq(s) + + lst = [] # a list of tuples, each tuple being (word, difficulty level) + for x in L: + word = x[0] + if word in d: + lst.append((word, d[word])) + + lst2 = sort_in_descending_order(lst) # most difficult words on top + #print(lst2) + count = 0 + geometric = 1 + for t in lst2: + word = t[0] + hard = t[1] + geometric = geometric * (hard) + count += 1 + if count >= 20: # we look for n most difficult words + return geometric**(1/count) + + return geometric**(1/max(count,1)) + + + +if __name__ == '__main__': + + + d1 = load_record('frequency.p') + #print(d1) + + d2 = load_record('words_and_tests.p') + #print(d2) + + + d3 = get_difficulty_level(d1, d2) + + s = ''' +South Lawn +11:53 A.M. EDT +THE PRESIDENT: Hi, everybody. Hi. How are you? So, the stock market is doing very well. +The economy is booming. We have a new record in sight. It could happen even today. +But we have a new stock market record. I think it’ll be about 118 times that we’ve broken the record. +Jobs look phenomenal. + ''' + s = ''' +By the authority vested in me as President by the Constitution and the laws of the United States, after carefully considering the reports submitted to the Congress by the Energy Information Administration, including the report submitted in October 2019, and other relevant factors, including global economic conditions, increased oil production by certain countries, the global level of spare petroleum production capacity, and the availability of strategic reserves, I determine, pursuant to section 1245(d)(4)(B) and (C) of the National Defense Authorization Act for Fiscal Year 2012, Public Law 112-81, and consistent with prior determinations, that there is a sufficient supply of petroleum and petroleum products from countries other than Iran to permit a significant reduction in the volume of petroleum and petroleum products purchased from Iran by or through foreign financial institutions. + +''' + + s = ''' +Democrats keep their witnesses locked behind secure doors, then flood the press with carefully sculpted leaks and accusations, driving the Trump-corruption narrative. And so the party goes, galloping toward an impeachment vote that would overturn the will of the American voters—on a case built in secret. + +Conservative commentators keep noting that Mrs. Pelosi’s refusal to hold a vote on the House floor to authorize an official impeachment inquiry helps her caucus’s vulnerable members evade accountability. But there’s a more practical and uglier reason for Democrats to skip the formalities. Normally an authorization vote would be followed by official rules on how the inquiry would proceed. Under today’s process, Mr. Schiff gets to make up the rules as he goes along. Behold the Lord High Impeacher. + +Democrats view control over the narrative as essential, having learned from their Russia-collusion escapade the perils of transparency. They banked on special counsel Robert Mueller’s investigation proving impeachment fodder, but got truth-bombed. Their subsequent open hearings on the subject—featuring Michael Cohen, Mr. Mueller and Corey Lewandowski —were, for the Democrats, embarrassing spectacles, at which Republicans punched gaping holes in their story line. + +Mr. Schiff is making sure that doesn’t happen again; he’ll present the story, on his terms. His rules mean he can issue that controlling decree about “only one” transcript and Democratic staff supervision of Republican members. It means he can bar the public, the press and even fellow representatives from hearings, even though they’re unclassified. +''' + + s = ''' +Unemployment today is at a 50-year low. There are more Americans working today than ever before. Median household income in the last two and half years has risen by more than $5,000. And that doesn’t even account for the savings from the President’s tax cuts or energy reforms for working families. + +Because of the President’s policies, America has added trillions of dollars of wealth to our economy while China’s economy continues to fall behind. + +To level the playing field for the American worker against unethical trade practices, President Trump levied tariffs on $250 billion in Chinese goods in 2018. And earlier this year, the President announced we would place tariffs on another $300 billion of Chinese goods if significant issues in our trading relationship were not resolved by December of this year. +''' + s = ''' +Needless to say, we see it very differently. Despite the great power competition that is underway, and America’s growing strength, we want better for China. That’s why, for the first time in decades, under President Donald Trump’s leadership, the United States is treating China’s leaders exactly how the leaders of any great world power should be treated — with respect, yes, but also with consistency and candor. +''' + s = ''' +Brexit is the scheduled withdrawal of the United Kingdom from the European Union. Following a June 2016 referendum, in which 51.9% voted to leave, the UK government formally announced the country's withdrawal in March 2017, starting a two-year process that was due to conclude with the UK withdrawing on 29 March 2019. As the UK parliament thrice voted against the negotiated withdrawal agreement, that deadline has been extended twice, and is currently 31 October 2019. The Benn Act, passed in September 2019, requires the government to seek a third extension. +''' + + s = ''' +The argument for Brexit +According to the BBC, the push to leave the EU was advocated mostly by the UK Independence Party and was not supported by the Prime Minister, David Cameron. Members of the UK Independence Party argued that Britain’s participation in the EU was a restrictive element for the country. + +As one of the EU’s primary initiatives is free movement within the region the party’s main arguments centered around regaining border control and reclaiming business rights. In addition, supporters of Brexit cited the high EU membership fees as a negative aspect of participation in the EU. It was argued that if the UK separates itself from the EU, these fees can be used to benefit the UK. + +The argument against Brexit +The Conservative Party and the Prime Minister were strongly in favor of remaining with the EU. As a result of the decision to discontinue its participation in the EU, the Prime Minister has made a public statement that he will be relinquishing his position. He believes that the country needs a leader with the same goals as the majority of the country. He has promised a new PM will be in place by early September. + +The argument against Brexit pertains mostly to the business benefits. The argument is that the UK receives business benefits by being able to participate in the single market system established by the EU. In response to the criticism against the open borders, proponents believe that the influx of immigrants helps develop an eager workforce and fuels public service projects. + +Leaders in favor of staying also worry about the political backlash that could possibly result from other countries who favored staying with the EU. In addition, proponents of remaining with the EU believe that being part of a wider community of nations provides economic and cultural strength, as well as an additional element of security. + +What does Brexit mean for the future? +While the decision marked a huge statement for the UK, the referendum vote is not legally binding. There are still many hurdles that must be dealt with before Brexit can become a reality. + +The UK is still subject to the laws of the EU until Britain’s exit becomes legal. In order for the UK to make its break official, the country needs to invoke Article 50. It is unclear exactly what this process will entail or how long it will take as Britain is the first country to take its leave of the EU. Once Article 50 has been formally invoked, the UK has two years to negotiate its departure with the other member states. But according to the BBC, “Extricating the UK from the EU will be extremely complex, and the process could drag on longer than that.” + +Amidst the aftermath of this shocking referendum vote, there is great uncertainty as political leaders decide what this means for the UK. + +''' + + + s = ''' +British Prime Minister Boris Johnson walks towards a voting station during the Brexit referendum in Britain, June 23, 2016. (Photo: EPA-EFE) + +LONDON – British Prime Minister Boris Johnson said Thursday he will likely ask Parliament to approve an election as part of an effort to break a Brexit deadlock. + +It is not clear if the vote, which Johnson wants to hold on Dec. 12, will take place as opposition lawmakers must also back the move. + +They are expected to vote on the measure on Monday. + +Johnson's announcement comes ahead of an expected decision Friday from the European Union over whether to delay Britain's exit from the bloc for three months. + +Britain's leader has been steadfastly opposed to any extension to the nation's scheduled Oct. 31 departure date from the EU, although in a letter to the leader of the opposition Labour Party this week he said he would accept a short technical postponement, "say to 15 or 30 November," to allow lawmakers to implement an EU withdrawal bill. + +Johnson's decision to offer to call an election follows lawmakers' rejection of his plan to rush through an EU exit bill that runs to hundreds of pages in just three days. They want more time to scrutinize the legislation and to make sure it does not leave the door open to a possible "no-deal" Brexit during future exit negotiations with the EU that will run through next year. A "no-deal" Brexit could dramatically harm Britain's economy. + +The prime minister was forced to ask for an extension to Britain's EU departure date after Britain's Parliament passed a law to ward off the threat of a "no-deal" Brexit. + +Johnson has repeatedly pledged to finalize the first stage, a transition deal, of Britain's EU divorce battle by Oct. 31. A second stage will involve negotiating its future relationship with the EU on trade, security and other salient issues. +''' + + + s = ''' +Thank you very much. We have a Cabinet meeting. We’ll have a few questions after grace. And, if you would, Ben, please do the honors. + +THE PRESIDENT: All right, thank you, Ben. That was a great job. Appreciate it. + +The economy is doing fantastically well. It’s getting very close to another record. We’ve had many records since we won office. We’re getting very close to another record. I don’t know if anybody saw it: The household median income for eight years of President Bush, it rose $400. For eight years of President Obama, it rose $975. And for two and half years of President Trump — they have it down as two and a half years — it rose $5,000, not including $2,000 for taxes. So it rose, let’s say, $7,000. So in two and a half years, we’re up $7,000, compared to $1,000, compared to $400. And that’s for eight years and eight years. + +That’s a number that just came out, but that’s a number that I don’t know how there could be any dispute or any — I’ve never heard a number like that, meaning the economy is doing fantastically well. + +We need — for our farmers, our manufacturers, for, frankly, unions and non-unions, we need USMCA to be voted on. If it’s voted on, it’ll pass. It’s up to Nancy Pelosi to put it up. If she puts it up, it’s going to pass. It’s going to be very bipartisan. It’s something that’s very much needed. It’ll be hundreds of thousands of jobs. + + +''' + + + + + #f = open('bbc-fulltext/bbc/entertainment/001.txt') + f = open('wordlist.txt') + s = f.read() + f.close() + + + + + print(text_difficulty_level(s, d3)) + + diff --git a/app/layout/partial/footer.html b/app/layout/partial/footer.html new file mode 100644 index 0000000..329d585 --- /dev/null +++ b/app/layout/partial/footer.html @@ -0,0 +1,21 @@ + + \ No newline at end of file diff --git a/app/layout/partial/header.html b/app/layout/partial/header.html new file mode 100644 index 0000000..3d0f70a --- /dev/null +++ b/app/layout/partial/header.html @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/app/main.py b/app/main.py new file mode 100644 index 0000000..d903bf4 --- /dev/null +++ b/app/main.py @@ -0,0 +1,114 @@ +#! /usr/bin/python3 +# -*- coding: utf-8 -*- + +########################################################################### +# Copyright 2019 (C) Hui Lan +# Written permission must be obtained from the author for commercial uses. +########################################################################### + +from Login import * +from Article import * +import Yaml +from user_service import userService +from account_service import accountService +app = Flask(__name__) +app.secret_key = 'lunch.time!' + +# 将蓝图注册到Lab app +app.register_blueprint(userService) +app.register_blueprint(accountService) + +path_prefix = '/var/www/wordfreq/wordfreq/' +path_prefix = './' # comment this line in deployment + + +def get_random_image(path): + ''' + 返回随机图 + :param path: 图片文件(JPEG格式),不包含后缀名 + :return: + ''' + img_path = random.choice(glob.glob(os.path.join(path, '*.jpg'))) + + return img_path[img_path.rfind('/static'):] + + +def get_random_ads(): + ''' + 返回随机广告 + :return: 一个广告(包含HTML标签) + ''' + ads = random.choice(['个性化分析精准提升', '你的专有单词本', '智能捕捉阅读弱点,针对性提高你的阅读水平']) + return ads + '。 试试吧!' + + +def appears_in_test(word, d): + ''' + 如果字符串里没有指定的单词,则返回逗号加单词 + :param word: 指定单词 + :param d: 字符串 + :return: 逗号加单词 + ''' + if not word in d: + return '' + else: + return ','.join(d[word]) + + +@app.route("/mark", methods=['GET', 'POST']) +def mark_word(): + ''' + 标记单词 + :return: 重定位到主界面 + ''' + if request.method == 'POST': + d = load_freq_history(path_prefix + 'static/frequency/frequency.p') + lst_history = pickle_idea.dict2lst(d) + lst = [] + for word in request.form.getlist('marked'): + lst.append((word, 1)) + d = pickle_idea.merge_frequency(lst, lst_history) + pickle_idea.save_frequency_to_pickle(d, path_prefix + 'static/frequency/frequency.p') + return redirect(url_for('mainpage')) + else: # 不回应GET请求 + return 'Under construction' + + +@app.route("/", methods=['GET', 'POST']) +def mainpage(): + ''' + 根据GET或POST方法来返回不同的主界面 + :return: 主界面 + ''' + if request.method == 'POST': # when we submit a form + content = request.form['content'] + f = WordFreq(content) + lst = f.get_freq() + # save history + d = load_freq_history(path_prefix + 'static/frequency/frequency.p') + lst_history = pickle_idea.dict2lst(d) + d = pickle_idea.merge_frequency(lst, lst_history) + pickle_idea.save_frequency_to_pickle(d, path_prefix + 'static/frequency/frequency.p') + return render_template('mainpage_post.html', lst=lst, yml=Yaml.yml) + + elif request.method == 'GET': # when we load a html page + random_ads = get_random_ads() + number_of_essays = total_number_of_essays() + d = load_freq_history(path_prefix + 'static/frequency/frequency.p') + d_len = len(d) + lst = sort_in_descending_order(pickle_idea.dict2lst(d)) + return render_template('mainpage_get.html', random_ads=random_ads, number_of_essays=number_of_essays, + d_len=d_len, lst=lst, yml=Yaml.yml) + + + +if __name__ == '__main__': + ''' + 运行程序 + ''' + # app.secret_key = os.urandom(16) + # app.run(debug=False, port='6000') + app.run(debug=True) + # app.run(debug=True, port='6000') + # app.run(host='0.0.0.0', debug=True, port='6000') + # print(mod5('123')) diff --git a/app/pickle_idea.py b/app/pickle_idea.py new file mode 100644 index 0000000..45bd19a --- /dev/null +++ b/app/pickle_idea.py @@ -0,0 +1,86 @@ +########################################################################### +# Copyright 2019 (C) Hui Lan +# Written permission must be obtained from the author for commercial uses. +########################################################################### + +# Purpose: dictionary & pickle as a simple means of database. +# Task: incorporate the functions into wordfreqCMD.py such that it will also show cumulative frequency. + +import pickle +from datetime import datetime + + +def lst2dict(lst, d): + ''' + Store the information in list lst to dictionary d. + Note: nothing is returned. + + ''' + for x in lst: + word = x[0] + freq = x[1] + if not word in d: + d[word] = freq + else: + d[word] += freq + + +def dict2lst(d): + return list(d.items()) # a list of (key, value) pairs + + +def merge_frequency(lst1, lst2): + d = {} + lst2dict(lst1, d) + lst2dict(lst2, d) + return d + + +def load_record(pickle_fname): + f = open(pickle_fname, 'rb') + d = pickle.load(f) + f.close() + return d + + +def save_frequency_to_pickle(d, pickle_fname): + f = open(pickle_fname, 'wb') + #exclusion_lst = ['one', 'no', 'has', 'had', 'do', 'that', 'have', 'by', 'not', 'but', 'we', 'this', 'my', 'him', 'so', 'or', 'as', 'are', 'it', 'from', 'with', 'be', 'can', 'for', 'an', 'if', 'who', 'whom', 'whose', 'which', 'the', 'to', 'a', 'of', 'and', 'you', 'i', 'he', 'she', 'they', 'me', 'was', 'were', 'is', 'in', 'at', 'on', 'their', 'his', 'her', 's', 'said', 'all', 'did', 'been', 'w'] + exclusion_lst = [] + d2 = {} + for k in d: + if not k in exclusion_lst and not k.isnumeric() and len(k) > 1: + d2[k] = d[k] + pickle.dump(d2, f) + f.close() + +def unfamiliar(path,word): + f = open(path,"rb") + dic = pickle.load(f) + dic[word] += [datetime.now().strftime('%Y%m%d%H%M')] + fp = open(path,"wb") + pickle.dump(dic,fp) + +def familiar(path,word): + f = open(path,"rb") + dic = pickle.load(f) + if len(dic[word])>1: + del dic[word][0] + else: + dic.pop(word) + fp = open(path,"wb") + pickle.dump(dic,fp) + +if __name__ == '__main__': + + lst1 = [('apple',2), ('banana',1)] + d = {} + lst2dict(lst1, d) # d will change + save_frequency_to_pickle(d, 'frequency.p') # frequency.p is our database + + + lst2 = [('banana',2), ('orange', 4)] + d = load_record('frequency.p') + lst1 = dict2lst(d) + d = merge_frequency(lst2, lst1) + print(d) diff --git a/app/pickle_idea2.py b/app/pickle_idea2.py new file mode 100644 index 0000000..4055fc4 --- /dev/null +++ b/app/pickle_idea2.py @@ -0,0 +1,89 @@ +########################################################################### +# Copyright 2019 (C) Hui Lan +# Written permission must be obtained from the author for commercial uses. +########################################################################### + + +# Purpose: dictionary & pickle as a simple means of database. +# Task: incorporate the functions into wordfreqCMD.py such that it will also show cumulative frequency. +# Note: unlike pick_idea.py, now the second item is not frequency, but a list of dates. + +import pickle +from datetime import datetime + +def lst2dict(lst, d): + ''' + Store the information in list lst to dictionary d. + Note: nothing is returned. + + ''' + for x in lst: + word = x[0] + dates = x[1] + if not word in d: + d[word] = dates + else: + d[word] += dates + +def deleteRecord(path,word): + with open(path, 'rb') as f: + db = pickle.load(f) + try: + db.pop(word) + except KeyError: + print("sorry") + with open(path, 'wb') as ff: + pickle.dump(db, ff) + +def dict2lst(d): + if len(d) > 0: + keys = list(d.keys()) + if isinstance(d[keys[0]], int): + lst = [] + for k in d: + lst.append((k, [datetime.now().strftime('%Y%m%d%H%M')])) + return lst + elif isinstance(d[keys[0]], list): + return list(d.items()) # a list of (key, value) pairs + + return [] + +def merge_frequency(lst1, lst2): + d = {} + lst2dict(lst1, d) + lst2dict(lst2, d) + return d + + +def load_record(pickle_fname): + f = open(pickle_fname, 'rb') + d = pickle.load(f) + f.close() + return d + + +def save_frequency_to_pickle(d, pickle_fname): + f = open(pickle_fname, 'wb') + exclusion_lst = ['one', 'no', 'has', 'had', 'do', 'that', 'have', 'by', 'not', 'but', 'we', 'this', 'my', 'him', 'so', 'or', 'as', 'are', 'it', 'from', 'with', 'be', 'can', 'for', 'an', 'if', 'who', 'whom', 'whose', 'which', 'the', 'to', 'a', 'of', 'and', 'you', 'i', 'he', 'she', 'they', 'me', 'was', 'were', 'is', 'in', 'at', 'on', 'their', 'his', 'her', 's', 'said', 'all', 'did', 'been', 'w'] + d2 = {} + for k in d: + if not k in exclusion_lst and not k.isnumeric() and not len(k) < 2: + d2[k] = list(sorted(set(d[k]))) + pickle.dump(d2, f) + f.close() + + + +if __name__ == '__main__': + + lst1 = [('apple',['201910251437', '201910251438']), ('banana',['201910251439'])] + d = {} + lst2dict(lst1, d) # d will change + save_frequency_to_pickle(d, 'frequency.p') # frequency.p is our database + + + lst2 = [('banana',['201910251439']), ('orange', ['201910251440', '201910251439'])] + d = load_record('frequency.p') + lst1 = dict2lst(d) + d = merge_frequency(lst2, lst1) + print(d) diff --git a/app/static/config.yml b/app/static/config.yml new file mode 100644 index 0000000..1ab8290 --- /dev/null +++ b/app/static/config.yml @@ -0,0 +1,17 @@ +# 全局引入的css文件地址 +css: + item: + - static/css/bootstrap.css + +# 全局引入的js文件地址 +js: + head: # 在页面加载之前加载 + # - static/js/APlayer.js + # - static/js/Meting.js + bottom: # 在页面加载完之后加载 + - static/js/fillword.js + - static/js/highlight.js + +# 高亮样式,目前仅支持修改颜色 +highlight: + color: ff0000 \ No newline at end of file diff --git a/app/static/css/bootstrap.css b/app/static/css/bootstrap.css new file mode 100644 index 0000000..dcde7a8 --- /dev/null +++ b/app/static/css/bootstrap.css @@ -0,0 +1,11192 @@ +@charset "UTF-8"; +/*! + * Bootstrap v5.0.2 (https://getbootstrap.com/) + * Copyright 2011-2021 The Bootstrap Authors + * Copyright 2011-2021 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +:root { + --bs-blue: #0d6efd; + --bs-indigo: #6610f2; + --bs-purple: #6f42c1; + --bs-pink: #d63384; + --bs-red: #dc3545; + --bs-orange: #fd7e14; + --bs-yellow: #ffc107; + --bs-green: #198754; + --bs-teal: #20c997; + --bs-cyan: #0dcaf0; + --bs-white: #fff; + --bs-gray: #6c757d; + --bs-gray-dark: #343a40; + --bs-primary: #0d6efd; + --bs-secondary: #6c757d; + --bs-success: #198754; + --bs-info: #0dcaf0; + --bs-warning: #ffc107; + --bs-danger: #dc3545; + --bs-light: #f8f9fa; + --bs-dark: #212529; + --bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + --bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0)) +} + +*, ::after, ::before { + box-sizing: border-box +} + +@media (prefers-reduced-motion: no-preference) { + :root { + scroll-behavior: smooth + } +} + +body { + margin: 0; + font-family: var(--bs-font-sans-serif); + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + background-color: #fff; + -webkit-text-size-adjust: 100%; + -webkit-tap-highlight-color: transparent +} + +hr { + margin: 1rem 0; + color: inherit; + background-color: currentColor; + border: 0; + opacity: .25 +} + +hr:not([size]) { + height: 1px +} + +.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: .5rem; + font-weight: 500; + line-height: 1.2 +} + +.h1, h1 { + font-size: calc(1.375rem + 1.5vw) +} + +@media (min-width: 1200px) { + .h1, h1 { + font-size: 2.5rem + } +} + +.h2, h2 { + font-size: calc(1.325rem + .9vw) +} + +@media (min-width: 1200px) { + .h2, h2 { + font-size: 2rem + } +} + +.h3, h3 { + font-size: calc(1.3rem + .6vw) +} + +@media (min-width: 1200px) { + .h3, h3 { + font-size: 1.75rem + } +} + +.h4, h4 { + font-size: calc(1.275rem + .3vw) +} + +@media (min-width: 1200px) { + .h4, h4 { + font-size: 1.5rem + } +} + +.h5, h5 { + font-size: 1.25rem +} + +.h6, h6 { + font-size: 1rem +} + +p { + margin-top: 0; + margin-bottom: 1rem +} + +abbr[data-bs-original-title], abbr[title] { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; + cursor: help; + -webkit-text-decoration-skip-ink: none; + text-decoration-skip-ink: none +} + +address { + margin-bottom: 1rem; + font-style: normal; + line-height: inherit +} + +ol, ul { + padding-left: 2rem +} + +dl, ol, ul { + margin-top: 0; + margin-bottom: 1rem +} + +ol ol, ol ul, ul ol, ul ul { + margin-bottom: 0 +} + +dt { + font-weight: 700 +} + +dd { + margin-bottom: .5rem; + margin-left: 0 +} + +blockquote { + margin: 0 0 1rem +} + +b, strong { + font-weight: bolder +} + +.small, small { + font-size: .875em +} + +.mark, mark { + background-color: #FFFF00 +} + +sub, sup { + position: relative; + font-size: .75em; + line-height: 0; + vertical-align: baseline +} + +sub { + bottom: -.25em +} + +sup { + top: -.5em +} + +a { + color: #0d6efd; + text-decoration: underline +} + +a:hover { + color: #0a58ca +} + +a:not([href]):not([class]), a:not([href]):not([class]):hover { + color: inherit; + text-decoration: none +} + +code, kbd, pre, samp { + font-family: var(--bs-font-monospace); + font-size: 1em; + direction: ltr; + unicode-bidi: bidi-override +} + +pre { + display: block; + margin-top: 0; + margin-bottom: 1rem; + overflow: auto; + font-size: .875em +} + +pre code { + font-size: inherit; + color: inherit; + word-break: normal +} + +code { + font-size: .875em; + color: #d63384; + word-wrap: break-word +} + +a > code { + color: inherit +} + +kbd { + padding: .2rem .4rem; + font-size: .875em; + color: #fff; + background-color: #212529; + border-radius: .2rem +} + +kbd kbd { + padding: 0; + font-size: 1em; + font-weight: 700 +} + +figure { + margin: 0 0 1rem +} + +img, svg { + vertical-align: middle +} + +table { + caption-side: bottom; + border-collapse: collapse +} + +caption { + padding-top: .5rem; + padding-bottom: .5rem; + color: #6c757d; + text-align: left +} + +th { + text-align: inherit; + text-align: -webkit-match-parent +} + +tbody, td, tfoot, th, thead, tr { + border-color: inherit; + border-style: solid; + border-width: 0 +} + +label { + display: inline-block +} + +button { + border-radius: 0 +} + +button:focus:not(:focus-visible) { + outline: 0 +} + +button, input, optgroup, select, textarea { + margin: 0; + font-family: inherit; + font-size: inherit; + line-height: inherit +} + +button, select { + text-transform: none +} + +[role=button] { + cursor: pointer +} + +select { + word-wrap: normal +} + +select:disabled { + opacity: 1 +} + +[list]::-webkit-calendar-picker-indicator { + display: none +} + +[type=button], [type=reset], [type=submit], button { + -webkit-appearance: button +} + +[type=button]:not(:disabled), [type=reset]:not(:disabled), [type=submit]:not(:disabled), button:not(:disabled) { + cursor: pointer +} + +::-moz-focus-inner { + padding: 0; + border-style: none +} + +textarea { + resize: vertical +} + +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0 +} + +legend { + float: left; + width: 100%; + padding: 0; + margin-bottom: .5rem; + font-size: calc(1.275rem + .3vw); + line-height: inherit +} + +@media (min-width: 1200px) { + legend { + font-size: 1.5rem + } +} + +legend + * { + clear: left +} + +::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-fields-wrapper, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-text, ::-webkit-datetime-edit-year-field { + padding: 0 +} + +::-webkit-inner-spin-button { + height: auto +} + +[type=search] { + outline-offset: -2px; + -webkit-appearance: textfield +} + +::-webkit-search-decoration { + -webkit-appearance: none +} + +::-webkit-color-swatch-wrapper { + padding: 0 +} + +::file-selector-button { + font: inherit +} + +::-webkit-file-upload-button { + font: inherit; + -webkit-appearance: button +} + +output { + display: inline-block +} + +iframe { + border: 0 +} + +summary { + display: list-item; + cursor: pointer +} + +progress { + vertical-align: baseline +} + +[hidden] { + display: none !important +} + +.lead { + font-size: 1.25rem; + font-weight: 300 +} + +.display-1 { + font-size: calc(1.625rem + 4.5vw); + font-weight: 300; + line-height: 1.2 +} + +@media (min-width: 1200px) { + .display-1 { + font-size: 5rem + } +} + +.display-2 { + font-size: calc(1.575rem + 3.9vw); + font-weight: 300; + line-height: 1.2 +} + +@media (min-width: 1200px) { + .display-2 { + font-size: 4.5rem + } +} + +.display-3 { + font-size: calc(1.525rem + 3.3vw); + font-weight: 300; + line-height: 1.2 +} + +@media (min-width: 1200px) { + .display-3 { + font-size: 4rem + } +} + +.display-4 { + font-size: calc(1.475rem + 2.7vw); + font-weight: 300; + line-height: 1.2 +} + +@media (min-width: 1200px) { + .display-4 { + font-size: 3.5rem + } +} + +.display-5 { + font-size: calc(1.425rem + 2.1vw); + font-weight: 300; + line-height: 1.2 +} + +@media (min-width: 1200px) { + .display-5 { + font-size: 3rem + } +} + +.display-6 { + font-size: calc(1.375rem + 1.5vw); + font-weight: 300; + line-height: 1.2 +} + +@media (min-width: 1200px) { + .display-6 { + font-size: 2.5rem + } +} + +.list-unstyled { + padding-left: 0; + list-style: none +} + +.list-inline { + padding-left: 0; + list-style: none +} + +.list-inline-item { + display: inline-block +} + +.list-inline-item:not(:last-child) { + margin-right: .5rem +} + +.initialism { + font-size: .875em; + text-transform: uppercase +} + +.blockquote { + margin-bottom: 1rem; + font-size: 1.25rem +} + +.blockquote > :last-child { + margin-bottom: 0 +} + +.blockquote-footer { + margin-top: -1rem; + margin-bottom: 1rem; + font-size: .875em; + color: #6c757d +} + +.blockquote-footer::before { + content: "— " +} + +.img-fluid { + max-width: 100%; + height: auto +} + +.img-thumbnail { + padding: .25rem; + background-color: #fff; + border: 1px solid #dee2e6; + border-radius: .25rem; + max-width: 100%; + height: auto +} + +.figure { + display: inline-block +} + +.figure-img { + margin-bottom: .5rem; + line-height: 1 +} + +.figure-caption { + font-size: .875em; + color: #6c757d +} + +.container, .container-fluid, .container-lg, .container-md, .container-sm, .container-xl, .container-xxl { + width: 100%; + padding-right: var(--bs-gutter-x, .75rem); + padding-left: var(--bs-gutter-x, .75rem); + margin-right: auto; + margin-left: auto +} + +@media (min-width: 576px) { + .container, .container-sm { + max-width: 540px + } +} + +@media (min-width: 768px) { + .container, .container-md, .container-sm { + max-width: 720px + } +} + +@media (min-width: 992px) { + .container, .container-lg, .container-md, .container-sm { + max-width: 960px + } +} + +@media (min-width: 1200px) { + .container, .container-lg, .container-md, .container-sm, .container-xl { + max-width: 1140px + } +} + +@media (min-width: 1400px) { + .container, .container-lg, .container-md, .container-sm, .container-xl, .container-xxl { + max-width: 1320px + } +} + +.row { + --bs-gutter-x: 1.5rem; + --bs-gutter-y: 0; + display: flex; + flex-wrap: wrap; + margin-top: calc(var(--bs-gutter-y) * -1); + margin-right: calc(var(--bs-gutter-x) * -.5); + margin-left: calc(var(--bs-gutter-x) * -.5) +} + +.row > * { + flex-shrink: 0; + width: 100%; + max-width: 100%; + padding-right: calc(var(--bs-gutter-x) * .5); + padding-left: calc(var(--bs-gutter-x) * .5); + margin-top: var(--bs-gutter-y) +} + +.col { + flex: 1 0 0% +} + +.row-cols-auto > * { + flex: 0 0 auto; + width: auto +} + +.row-cols-1 > * { + flex: 0 0 auto; + width: 100% +} + +.row-cols-2 > * { + flex: 0 0 auto; + width: 50% +} + +.row-cols-3 > * { + flex: 0 0 auto; + width: 33.3333333333% +} + +.row-cols-4 > * { + flex: 0 0 auto; + width: 25% +} + +.row-cols-5 > * { + flex: 0 0 auto; + width: 20% +} + +.row-cols-6 > * { + flex: 0 0 auto; + width: 16.6666666667% +} + +@media (min-width: 576px) { + .col-sm { + flex: 1 0 0% + } + + .row-cols-sm-auto > * { + flex: 0 0 auto; + width: auto + } + + .row-cols-sm-1 > * { + flex: 0 0 auto; + width: 100% + } + + .row-cols-sm-2 > * { + flex: 0 0 auto; + width: 50% + } + + .row-cols-sm-3 > * { + flex: 0 0 auto; + width: 33.3333333333% + } + + .row-cols-sm-4 > * { + flex: 0 0 auto; + width: 25% + } + + .row-cols-sm-5 > * { + flex: 0 0 auto; + width: 20% + } + + .row-cols-sm-6 > * { + flex: 0 0 auto; + width: 16.6666666667% + } +} + +@media (min-width: 768px) { + .col-md { + flex: 1 0 0% + } + + .row-cols-md-auto > * { + flex: 0 0 auto; + width: auto + } + + .row-cols-md-1 > * { + flex: 0 0 auto; + width: 100% + } + + .row-cols-md-2 > * { + flex: 0 0 auto; + width: 50% + } + + .row-cols-md-3 > * { + flex: 0 0 auto; + width: 33.3333333333% + } + + .row-cols-md-4 > * { + flex: 0 0 auto; + width: 25% + } + + .row-cols-md-5 > * { + flex: 0 0 auto; + width: 20% + } + + .row-cols-md-6 > * { + flex: 0 0 auto; + width: 16.6666666667% + } +} + +@media (min-width: 992px) { + .col-lg { + flex: 1 0 0% + } + + .row-cols-lg-auto > * { + flex: 0 0 auto; + width: auto + } + + .row-cols-lg-1 > * { + flex: 0 0 auto; + width: 100% + } + + .row-cols-lg-2 > * { + flex: 0 0 auto; + width: 50% + } + + .row-cols-lg-3 > * { + flex: 0 0 auto; + width: 33.3333333333% + } + + .row-cols-lg-4 > * { + flex: 0 0 auto; + width: 25% + } + + .row-cols-lg-5 > * { + flex: 0 0 auto; + width: 20% + } + + .row-cols-lg-6 > * { + flex: 0 0 auto; + width: 16.6666666667% + } +} + +@media (min-width: 1200px) { + .col-xl { + flex: 1 0 0% + } + + .row-cols-xl-auto > * { + flex: 0 0 auto; + width: auto + } + + .row-cols-xl-1 > * { + flex: 0 0 auto; + width: 100% + } + + .row-cols-xl-2 > * { + flex: 0 0 auto; + width: 50% + } + + .row-cols-xl-3 > * { + flex: 0 0 auto; + width: 33.3333333333% + } + + .row-cols-xl-4 > * { + flex: 0 0 auto; + width: 25% + } + + .row-cols-xl-5 > * { + flex: 0 0 auto; + width: 20% + } + + .row-cols-xl-6 > * { + flex: 0 0 auto; + width: 16.6666666667% + } +} + +@media (min-width: 1400px) { + .col-xxl { + flex: 1 0 0% + } + + .row-cols-xxl-auto > * { + flex: 0 0 auto; + width: auto + } + + .row-cols-xxl-1 > * { + flex: 0 0 auto; + width: 100% + } + + .row-cols-xxl-2 > * { + flex: 0 0 auto; + width: 50% + } + + .row-cols-xxl-3 > * { + flex: 0 0 auto; + width: 33.3333333333% + } + + .row-cols-xxl-4 > * { + flex: 0 0 auto; + width: 25% + } + + .row-cols-xxl-5 > * { + flex: 0 0 auto; + width: 20% + } + + .row-cols-xxl-6 > * { + flex: 0 0 auto; + width: 16.6666666667% + } +} + +.col-auto { + flex: 0 0 auto; + width: auto +} + +.col-1 { + flex: 0 0 auto; + width: 8.33333333% +} + +.col-2 { + flex: 0 0 auto; + width: 16.66666667% +} + +.col-3 { + flex: 0 0 auto; + width: 25% +} + +.col-4 { + flex: 0 0 auto; + width: 33.33333333% +} + +.col-5 { + flex: 0 0 auto; + width: 41.66666667% +} + +.col-6 { + flex: 0 0 auto; + width: 50% +} + +.col-7 { + flex: 0 0 auto; + width: 58.33333333% +} + +.col-8 { + flex: 0 0 auto; + width: 66.66666667% +} + +.col-9 { + flex: 0 0 auto; + width: 75% +} + +.col-10 { + flex: 0 0 auto; + width: 83.33333333% +} + +.col-11 { + flex: 0 0 auto; + width: 91.66666667% +} + +.col-12 { + flex: 0 0 auto; + width: 100% +} + +.offset-1 { + margin-left: 8.33333333% +} + +.offset-2 { + margin-left: 16.66666667% +} + +.offset-3 { + margin-left: 25% +} + +.offset-4 { + margin-left: 33.33333333% +} + +.offset-5 { + margin-left: 41.66666667% +} + +.offset-6 { + margin-left: 50% +} + +.offset-7 { + margin-left: 58.33333333% +} + +.offset-8 { + margin-left: 66.66666667% +} + +.offset-9 { + margin-left: 75% +} + +.offset-10 { + margin-left: 83.33333333% +} + +.offset-11 { + margin-left: 91.66666667% +} + +.g-0, .gx-0 { + --bs-gutter-x: 0 +} + +.g-0, .gy-0 { + --bs-gutter-y: 0 +} + +.g-1, .gx-1 { + --bs-gutter-x: 0.25rem +} + +.g-1, .gy-1 { + --bs-gutter-y: 0.25rem +} + +.g-2, .gx-2 { + --bs-gutter-x: 0.5rem +} + +.g-2, .gy-2 { + --bs-gutter-y: 0.5rem +} + +.g-3, .gx-3 { + --bs-gutter-x: 1rem +} + +.g-3, .gy-3 { + --bs-gutter-y: 1rem +} + +.g-4, .gx-4 { + --bs-gutter-x: 1.5rem +} + +.g-4, .gy-4 { + --bs-gutter-y: 1.5rem +} + +.g-5, .gx-5 { + --bs-gutter-x: 3rem +} + +.g-5, .gy-5 { + --bs-gutter-y: 3rem +} + +@media (min-width: 576px) { + .col-sm-auto { + flex: 0 0 auto; + width: auto + } + + .col-sm-1 { + flex: 0 0 auto; + width: 8.33333333% + } + + .col-sm-2 { + flex: 0 0 auto; + width: 16.66666667% + } + + .col-sm-3 { + flex: 0 0 auto; + width: 25% + } + + .col-sm-4 { + flex: 0 0 auto; + width: 33.33333333% + } + + .col-sm-5 { + flex: 0 0 auto; + width: 41.66666667% + } + + .col-sm-6 { + flex: 0 0 auto; + width: 50% + } + + .col-sm-7 { + flex: 0 0 auto; + width: 58.33333333% + } + + .col-sm-8 { + flex: 0 0 auto; + width: 66.66666667% + } + + .col-sm-9 { + flex: 0 0 auto; + width: 75% + } + + .col-sm-10 { + flex: 0 0 auto; + width: 83.33333333% + } + + .col-sm-11 { + flex: 0 0 auto; + width: 91.66666667% + } + + .col-sm-12 { + flex: 0 0 auto; + width: 100% + } + + .offset-sm-0 { + margin-left: 0 + } + + .offset-sm-1 { + margin-left: 8.33333333% + } + + .offset-sm-2 { + margin-left: 16.66666667% + } + + .offset-sm-3 { + margin-left: 25% + } + + .offset-sm-4 { + margin-left: 33.33333333% + } + + .offset-sm-5 { + margin-left: 41.66666667% + } + + .offset-sm-6 { + margin-left: 50% + } + + .offset-sm-7 { + margin-left: 58.33333333% + } + + .offset-sm-8 { + margin-left: 66.66666667% + } + + .offset-sm-9 { + margin-left: 75% + } + + .offset-sm-10 { + margin-left: 83.33333333% + } + + .offset-sm-11 { + margin-left: 91.66666667% + } + + .g-sm-0, .gx-sm-0 { + --bs-gutter-x: 0 + } + + .g-sm-0, .gy-sm-0 { + --bs-gutter-y: 0 + } + + .g-sm-1, .gx-sm-1 { + --bs-gutter-x: 0.25rem + } + + .g-sm-1, .gy-sm-1 { + --bs-gutter-y: 0.25rem + } + + .g-sm-2, .gx-sm-2 { + --bs-gutter-x: 0.5rem + } + + .g-sm-2, .gy-sm-2 { + --bs-gutter-y: 0.5rem + } + + .g-sm-3, .gx-sm-3 { + --bs-gutter-x: 1rem + } + + .g-sm-3, .gy-sm-3 { + --bs-gutter-y: 1rem + } + + .g-sm-4, .gx-sm-4 { + --bs-gutter-x: 1.5rem + } + + .g-sm-4, .gy-sm-4 { + --bs-gutter-y: 1.5rem + } + + .g-sm-5, .gx-sm-5 { + --bs-gutter-x: 3rem + } + + .g-sm-5, .gy-sm-5 { + --bs-gutter-y: 3rem + } +} + +@media (min-width: 768px) { + .col-md-auto { + flex: 0 0 auto; + width: auto + } + + .col-md-1 { + flex: 0 0 auto; + width: 8.33333333% + } + + .col-md-2 { + flex: 0 0 auto; + width: 16.66666667% + } + + .col-md-3 { + flex: 0 0 auto; + width: 25% + } + + .col-md-4 { + flex: 0 0 auto; + width: 33.33333333% + } + + .col-md-5 { + flex: 0 0 auto; + width: 41.66666667% + } + + .col-md-6 { + flex: 0 0 auto; + width: 50% + } + + .col-md-7 { + flex: 0 0 auto; + width: 58.33333333% + } + + .col-md-8 { + flex: 0 0 auto; + width: 66.66666667% + } + + .col-md-9 { + flex: 0 0 auto; + width: 75% + } + + .col-md-10 { + flex: 0 0 auto; + width: 83.33333333% + } + + .col-md-11 { + flex: 0 0 auto; + width: 91.66666667% + } + + .col-md-12 { + flex: 0 0 auto; + width: 100% + } + + .offset-md-0 { + margin-left: 0 + } + + .offset-md-1 { + margin-left: 8.33333333% + } + + .offset-md-2 { + margin-left: 16.66666667% + } + + .offset-md-3 { + margin-left: 25% + } + + .offset-md-4 { + margin-left: 33.33333333% + } + + .offset-md-5 { + margin-left: 41.66666667% + } + + .offset-md-6 { + margin-left: 50% + } + + .offset-md-7 { + margin-left: 58.33333333% + } + + .offset-md-8 { + margin-left: 66.66666667% + } + + .offset-md-9 { + margin-left: 75% + } + + .offset-md-10 { + margin-left: 83.33333333% + } + + .offset-md-11 { + margin-left: 91.66666667% + } + + .g-md-0, .gx-md-0 { + --bs-gutter-x: 0 + } + + .g-md-0, .gy-md-0 { + --bs-gutter-y: 0 + } + + .g-md-1, .gx-md-1 { + --bs-gutter-x: 0.25rem + } + + .g-md-1, .gy-md-1 { + --bs-gutter-y: 0.25rem + } + + .g-md-2, .gx-md-2 { + --bs-gutter-x: 0.5rem + } + + .g-md-2, .gy-md-2 { + --bs-gutter-y: 0.5rem + } + + .g-md-3, .gx-md-3 { + --bs-gutter-x: 1rem + } + + .g-md-3, .gy-md-3 { + --bs-gutter-y: 1rem + } + + .g-md-4, .gx-md-4 { + --bs-gutter-x: 1.5rem + } + + .g-md-4, .gy-md-4 { + --bs-gutter-y: 1.5rem + } + + .g-md-5, .gx-md-5 { + --bs-gutter-x: 3rem + } + + .g-md-5, .gy-md-5 { + --bs-gutter-y: 3rem + } +} + +@media (min-width: 992px) { + .col-lg-auto { + flex: 0 0 auto; + width: auto + } + + .col-lg-1 { + flex: 0 0 auto; + width: 8.33333333% + } + + .col-lg-2 { + flex: 0 0 auto; + width: 16.66666667% + } + + .col-lg-3 { + flex: 0 0 auto; + width: 25% + } + + .col-lg-4 { + flex: 0 0 auto; + width: 33.33333333% + } + + .col-lg-5 { + flex: 0 0 auto; + width: 41.66666667% + } + + .col-lg-6 { + flex: 0 0 auto; + width: 50% + } + + .col-lg-7 { + flex: 0 0 auto; + width: 58.33333333% + } + + .col-lg-8 { + flex: 0 0 auto; + width: 66.66666667% + } + + .col-lg-9 { + flex: 0 0 auto; + width: 75% + } + + .col-lg-10 { + flex: 0 0 auto; + width: 83.33333333% + } + + .col-lg-11 { + flex: 0 0 auto; + width: 91.66666667% + } + + .col-lg-12 { + flex: 0 0 auto; + width: 100% + } + + .offset-lg-0 { + margin-left: 0 + } + + .offset-lg-1 { + margin-left: 8.33333333% + } + + .offset-lg-2 { + margin-left: 16.66666667% + } + + .offset-lg-3 { + margin-left: 25% + } + + .offset-lg-4 { + margin-left: 33.33333333% + } + + .offset-lg-5 { + margin-left: 41.66666667% + } + + .offset-lg-6 { + margin-left: 50% + } + + .offset-lg-7 { + margin-left: 58.33333333% + } + + .offset-lg-8 { + margin-left: 66.66666667% + } + + .offset-lg-9 { + margin-left: 75% + } + + .offset-lg-10 { + margin-left: 83.33333333% + } + + .offset-lg-11 { + margin-left: 91.66666667% + } + + .g-lg-0, .gx-lg-0 { + --bs-gutter-x: 0 + } + + .g-lg-0, .gy-lg-0 { + --bs-gutter-y: 0 + } + + .g-lg-1, .gx-lg-1 { + --bs-gutter-x: 0.25rem + } + + .g-lg-1, .gy-lg-1 { + --bs-gutter-y: 0.25rem + } + + .g-lg-2, .gx-lg-2 { + --bs-gutter-x: 0.5rem + } + + .g-lg-2, .gy-lg-2 { + --bs-gutter-y: 0.5rem + } + + .g-lg-3, .gx-lg-3 { + --bs-gutter-x: 1rem + } + + .g-lg-3, .gy-lg-3 { + --bs-gutter-y: 1rem + } + + .g-lg-4, .gx-lg-4 { + --bs-gutter-x: 1.5rem + } + + .g-lg-4, .gy-lg-4 { + --bs-gutter-y: 1.5rem + } + + .g-lg-5, .gx-lg-5 { + --bs-gutter-x: 3rem + } + + .g-lg-5, .gy-lg-5 { + --bs-gutter-y: 3rem + } +} + +@media (min-width: 1200px) { + .col-xl-auto { + flex: 0 0 auto; + width: auto + } + + .col-xl-1 { + flex: 0 0 auto; + width: 8.33333333% + } + + .col-xl-2 { + flex: 0 0 auto; + width: 16.66666667% + } + + .col-xl-3 { + flex: 0 0 auto; + width: 25% + } + + .col-xl-4 { + flex: 0 0 auto; + width: 33.33333333% + } + + .col-xl-5 { + flex: 0 0 auto; + width: 41.66666667% + } + + .col-xl-6 { + flex: 0 0 auto; + width: 50% + } + + .col-xl-7 { + flex: 0 0 auto; + width: 58.33333333% + } + + .col-xl-8 { + flex: 0 0 auto; + width: 66.66666667% + } + + .col-xl-9 { + flex: 0 0 auto; + width: 75% + } + + .col-xl-10 { + flex: 0 0 auto; + width: 83.33333333% + } + + .col-xl-11 { + flex: 0 0 auto; + width: 91.66666667% + } + + .col-xl-12 { + flex: 0 0 auto; + width: 100% + } + + .offset-xl-0 { + margin-left: 0 + } + + .offset-xl-1 { + margin-left: 8.33333333% + } + + .offset-xl-2 { + margin-left: 16.66666667% + } + + .offset-xl-3 { + margin-left: 25% + } + + .offset-xl-4 { + margin-left: 33.33333333% + } + + .offset-xl-5 { + margin-left: 41.66666667% + } + + .offset-xl-6 { + margin-left: 50% + } + + .offset-xl-7 { + margin-left: 58.33333333% + } + + .offset-xl-8 { + margin-left: 66.66666667% + } + + .offset-xl-9 { + margin-left: 75% + } + + .offset-xl-10 { + margin-left: 83.33333333% + } + + .offset-xl-11 { + margin-left: 91.66666667% + } + + .g-xl-0, .gx-xl-0 { + --bs-gutter-x: 0 + } + + .g-xl-0, .gy-xl-0 { + --bs-gutter-y: 0 + } + + .g-xl-1, .gx-xl-1 { + --bs-gutter-x: 0.25rem + } + + .g-xl-1, .gy-xl-1 { + --bs-gutter-y: 0.25rem + } + + .g-xl-2, .gx-xl-2 { + --bs-gutter-x: 0.5rem + } + + .g-xl-2, .gy-xl-2 { + --bs-gutter-y: 0.5rem + } + + .g-xl-3, .gx-xl-3 { + --bs-gutter-x: 1rem + } + + .g-xl-3, .gy-xl-3 { + --bs-gutter-y: 1rem + } + + .g-xl-4, .gx-xl-4 { + --bs-gutter-x: 1.5rem + } + + .g-xl-4, .gy-xl-4 { + --bs-gutter-y: 1.5rem + } + + .g-xl-5, .gx-xl-5 { + --bs-gutter-x: 3rem + } + + .g-xl-5, .gy-xl-5 { + --bs-gutter-y: 3rem + } +} + +@media (min-width: 1400px) { + .col-xxl-auto { + flex: 0 0 auto; + width: auto + } + + .col-xxl-1 { + flex: 0 0 auto; + width: 8.33333333% + } + + .col-xxl-2 { + flex: 0 0 auto; + width: 16.66666667% + } + + .col-xxl-3 { + flex: 0 0 auto; + width: 25% + } + + .col-xxl-4 { + flex: 0 0 auto; + width: 33.33333333% + } + + .col-xxl-5 { + flex: 0 0 auto; + width: 41.66666667% + } + + .col-xxl-6 { + flex: 0 0 auto; + width: 50% + } + + .col-xxl-7 { + flex: 0 0 auto; + width: 58.33333333% + } + + .col-xxl-8 { + flex: 0 0 auto; + width: 66.66666667% + } + + .col-xxl-9 { + flex: 0 0 auto; + width: 75% + } + + .col-xxl-10 { + flex: 0 0 auto; + width: 83.33333333% + } + + .col-xxl-11 { + flex: 0 0 auto; + width: 91.66666667% + } + + .col-xxl-12 { + flex: 0 0 auto; + width: 100% + } + + .offset-xxl-0 { + margin-left: 0 + } + + .offset-xxl-1 { + margin-left: 8.33333333% + } + + .offset-xxl-2 { + margin-left: 16.66666667% + } + + .offset-xxl-3 { + margin-left: 25% + } + + .offset-xxl-4 { + margin-left: 33.33333333% + } + + .offset-xxl-5 { + margin-left: 41.66666667% + } + + .offset-xxl-6 { + margin-left: 50% + } + + .offset-xxl-7 { + margin-left: 58.33333333% + } + + .offset-xxl-8 { + margin-left: 66.66666667% + } + + .offset-xxl-9 { + margin-left: 75% + } + + .offset-xxl-10 { + margin-left: 83.33333333% + } + + .offset-xxl-11 { + margin-left: 91.66666667% + } + + .g-xxl-0, .gx-xxl-0 { + --bs-gutter-x: 0 + } + + .g-xxl-0, .gy-xxl-0 { + --bs-gutter-y: 0 + } + + .g-xxl-1, .gx-xxl-1 { + --bs-gutter-x: 0.25rem + } + + .g-xxl-1, .gy-xxl-1 { + --bs-gutter-y: 0.25rem + } + + .g-xxl-2, .gx-xxl-2 { + --bs-gutter-x: 0.5rem + } + + .g-xxl-2, .gy-xxl-2 { + --bs-gutter-y: 0.5rem + } + + .g-xxl-3, .gx-xxl-3 { + --bs-gutter-x: 1rem + } + + .g-xxl-3, .gy-xxl-3 { + --bs-gutter-y: 1rem + } + + .g-xxl-4, .gx-xxl-4 { + --bs-gutter-x: 1.5rem + } + + .g-xxl-4, .gy-xxl-4 { + --bs-gutter-y: 1.5rem + } + + .g-xxl-5, .gx-xxl-5 { + --bs-gutter-x: 3rem + } + + .g-xxl-5, .gy-xxl-5 { + --bs-gutter-y: 3rem + } +} + +.table { + --bs-table-bg: transparent; + --bs-table-accent-bg: transparent; + --bs-table-striped-color: #212529; + --bs-table-striped-bg: rgba(0, 0, 0, 0.05); + --bs-table-active-color: #212529; + --bs-table-active-bg: rgba(0, 0, 0, 0.1); + --bs-table-hover-color: #212529; + --bs-table-hover-bg: rgba(0, 0, 0, 0.075); + width: 100%; + margin-bottom: 1rem; + color: #212529; + vertical-align: top; + border-color: #dee2e6 +} + +.table > :not(caption) > * > * { + padding: .5rem .5rem; + background-color: var(--bs-table-bg); + border-bottom-width: 1px; + box-shadow: inset 0 0 0 9999px var(--bs-table-accent-bg) +} + +.table > tbody { + vertical-align: inherit +} + +.table > thead { + vertical-align: bottom +} + +.table > :not(:last-child) > :last-child > * { + border-bottom-color: currentColor +} + +.caption-top { + caption-side: top +} + +.table-sm > :not(caption) > * > * { + padding: .25rem .25rem +} + +.table-bordered > :not(caption) > * { + border-width: 1px 0 +} + +.table-bordered > :not(caption) > * > * { + border-width: 0 1px +} + +.table-borderless > :not(caption) > * > * { + border-bottom-width: 0 +} + +.table-striped > tbody > tr:nth-of-type(odd) { + --bs-table-accent-bg: var(--bs-table-striped-bg); + color: var(--bs-table-striped-color) +} + +.table-active { + --bs-table-accent-bg: var(--bs-table-active-bg); + color: var(--bs-table-active-color) +} + +.table-hover > tbody > tr:hover { + --bs-table-accent-bg: var(--bs-table-hover-bg); + color: var(--bs-table-hover-color) +} + +.table-primary { + --bs-table-bg: #cfe2ff; + --bs-table-striped-bg: #c5d7f2; + --bs-table-striped-color: #000; + --bs-table-active-bg: #bacbe6; + --bs-table-active-color: #000; + --bs-table-hover-bg: #bfd1ec; + --bs-table-hover-color: #000; + color: #000; + border-color: #bacbe6 +} + +.table-secondary { + --bs-table-bg: #e2e3e5; + --bs-table-striped-bg: #d7d8da; + --bs-table-striped-color: #000; + --bs-table-active-bg: #cbccce; + --bs-table-active-color: #000; + --bs-table-hover-bg: #d1d2d4; + --bs-table-hover-color: #000; + color: #000; + border-color: #cbccce +} + +.table-success { + --bs-table-bg: #d1e7dd; + --bs-table-striped-bg: #c7dbd2; + --bs-table-striped-color: #000; + --bs-table-active-bg: #bcd0c7; + --bs-table-active-color: #000; + --bs-table-hover-bg: #c1d6cc; + --bs-table-hover-color: #000; + color: #000; + border-color: #bcd0c7 +} + +.table-info { + --bs-table-bg: #cff4fc; + --bs-table-striped-bg: #c5e8ef; + --bs-table-striped-color: #000; + --bs-table-active-bg: #badce3; + --bs-table-active-color: #000; + --bs-table-hover-bg: #bfe2e9; + --bs-table-hover-color: #000; + color: #000; + border-color: #badce3 +} + +.table-warning { + --bs-table-bg: #fff3cd; + --bs-table-striped-bg: #f2e7c3; + --bs-table-striped-color: #000; + --bs-table-active-bg: #e6dbb9; + --bs-table-active-color: #000; + --bs-table-hover-bg: #ece1be; + --bs-table-hover-color: #000; + color: #000; + border-color: #e6dbb9 +} + +.table-danger { + --bs-table-bg: #f8d7da; + --bs-table-striped-bg: #eccccf; + --bs-table-striped-color: #000; + --bs-table-active-bg: #dfc2c4; + --bs-table-active-color: #000; + --bs-table-hover-bg: #e5c7ca; + --bs-table-hover-color: #000; + color: #000; + border-color: #dfc2c4 +} + +.table-light { + --bs-table-bg: #f8f9fa; + --bs-table-striped-bg: #ecedee; + --bs-table-striped-color: #000; + --bs-table-active-bg: #dfe0e1; + --bs-table-active-color: #000; + --bs-table-hover-bg: #e5e6e7; + --bs-table-hover-color: #000; + color: #000; + border-color: #dfe0e1 +} + +.table-dark { + --bs-table-bg: #212529; + --bs-table-striped-bg: #2c3034; + --bs-table-striped-color: #fff; + --bs-table-active-bg: #373b3e; + --bs-table-active-color: #fff; + --bs-table-hover-bg: #323539; + --bs-table-hover-color: #fff; + color: #fff; + border-color: #373b3e +} + +.table-responsive { + overflow-x: auto; + -webkit-overflow-scrolling: touch +} + +@media (max-width: 575.98px) { + .table-responsive-sm { + overflow-x: auto; + -webkit-overflow-scrolling: touch + } +} + +@media (max-width: 767.98px) { + .table-responsive-md { + overflow-x: auto; + -webkit-overflow-scrolling: touch + } +} + +@media (max-width: 991.98px) { + .table-responsive-lg { + overflow-x: auto; + -webkit-overflow-scrolling: touch + } +} + +@media (max-width: 1199.98px) { + .table-responsive-xl { + overflow-x: auto; + -webkit-overflow-scrolling: touch + } +} + +@media (max-width: 1399.98px) { + .table-responsive-xxl { + overflow-x: auto; + -webkit-overflow-scrolling: touch + } +} + +.form-label { + margin-bottom: .5rem +} + +.col-form-label { + padding-top: calc(.375rem + 1px); + padding-bottom: calc(.375rem + 1px); + margin-bottom: 0; + font-size: inherit; + line-height: 1.5 +} + +.col-form-label-lg { + padding-top: calc(.5rem + 1px); + padding-bottom: calc(.5rem + 1px); + font-size: 1.25rem +} + +.col-form-label-sm { + padding-top: calc(.25rem + 1px); + padding-bottom: calc(.25rem + 1px); + font-size: .875rem +} + +.form-text { + margin-top: .25rem; + font-size: .875em; + color: #6c757d +} + +.form-control { + display: block; + width: 100%; + padding: .375rem .75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ced4da; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + border-radius: .25rem; + transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out +} + +@media (prefers-reduced-motion: reduce) { + .form-control { + transition: none + } +} + +.form-control[type=file] { + overflow: hidden +} + +.form-control[type=file]:not(:disabled):not([readonly]) { + cursor: pointer +} + +.form-control:focus { + color: #212529; + background-color: #fff; + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 .25rem rgba(13, 110, 253, .25) +} + +.form-control::-webkit-date-and-time-value { + height: 1.5em +} + +.form-control::-moz-placeholder { + color: #6c757d; + opacity: 1 +} + +.form-control::placeholder { + color: #6c757d; + opacity: 1 +} + +.form-control:disabled, .form-control[readonly] { + background-color: #e9ecef; + opacity: 1 +} + +.form-control::file-selector-button { + padding: .375rem .75rem; + margin: -.375rem -.75rem; + -webkit-margin-end: .75rem; + margin-inline-end: .75rem; + color: #212529; + background-color: #e9ecef; + pointer-events: none; + border-color: inherit; + border-style: solid; + border-width: 0; + border-inline-end-width: 1px; + border-radius: 0; + transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out +} + +@media (prefers-reduced-motion: reduce) { + .form-control::file-selector-button { + transition: none + } +} + +.form-control:hover:not(:disabled):not([readonly])::file-selector-button { + background-color: #dde0e3 +} + +.form-control::-webkit-file-upload-button { + padding: .375rem .75rem; + margin: -.375rem -.75rem; + -webkit-margin-end: .75rem; + margin-inline-end: .75rem; + color: #212529; + background-color: #e9ecef; + pointer-events: none; + border-color: inherit; + border-style: solid; + border-width: 0; + border-inline-end-width: 1px; + border-radius: 0; + -webkit-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out; + transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out +} + +@media (prefers-reduced-motion: reduce) { + .form-control::-webkit-file-upload-button { + -webkit-transition: none; + transition: none + } +} + +.form-control:hover:not(:disabled):not([readonly])::-webkit-file-upload-button { + background-color: #dde0e3 +} + +.form-control-plaintext { + display: block; + width: 100%; + padding: .375rem 0; + margin-bottom: 0; + line-height: 1.5; + color: #212529; + background-color: transparent; + border: solid transparent; + border-width: 1px 0 +} + +.form-control-plaintext.form-control-lg, .form-control-plaintext.form-control-sm { + padding-right: 0; + padding-left: 0 +} + +.form-control-sm { + min-height: calc(1.5em + (.5rem + 2px)); + padding: .25rem .5rem; + font-size: .875rem; + border-radius: .2rem +} + +.form-control-sm::file-selector-button { + padding: .25rem .5rem; + margin: -.25rem -.5rem; + -webkit-margin-end: .5rem; + margin-inline-end: .5rem +} + +.form-control-sm::-webkit-file-upload-button { + padding: .25rem .5rem; + margin: -.25rem -.5rem; + -webkit-margin-end: .5rem; + margin-inline-end: .5rem +} + +.form-control-lg { + min-height: calc(1.5em + (1rem + 2px)); + padding: .5rem 1rem; + font-size: 1.25rem; + border-radius: .3rem +} + +.form-control-lg::file-selector-button { + padding: .5rem 1rem; + margin: -.5rem -1rem; + -webkit-margin-end: 1rem; + margin-inline-end: 1rem +} + +.form-control-lg::-webkit-file-upload-button { + padding: .5rem 1rem; + margin: -.5rem -1rem; + -webkit-margin-end: 1rem; + margin-inline-end: 1rem +} + +textarea.form-control { + min-height: calc(1.5em + (.75rem + 2px)) +} + +textarea.form-control-sm { + min-height: calc(1.5em + (.5rem + 2px)) +} + +textarea.form-control-lg { + min-height: calc(1.5em + (1rem + 2px)) +} + +.form-control-color { + max-width: 3rem; + height: auto; + padding: .375rem +} + +.form-control-color:not(:disabled):not([readonly]) { + cursor: pointer +} + +.form-control-color::-moz-color-swatch { + height: 1.5em; + border-radius: .25rem +} + +.form-control-color::-webkit-color-swatch { + height: 1.5em; + border-radius: .25rem +} + +.form-select { + display: block; + width: 100%; + padding: .375rem 2.25rem .375rem .75rem; + -moz-padding-start: calc(0.75rem - 3px); + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + background-color: #fff; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right .75rem center; + background-size: 16px 12px; + border: 1px solid #ced4da; + border-radius: .25rem; + transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none +} + +@media (prefers-reduced-motion: reduce) { + .form-select { + transition: none + } +} + +.form-select:focus { + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 .25rem rgba(13, 110, 253, .25) +} + +.form-select[multiple], .form-select[size]:not([size="1"]) { + padding-right: .75rem; + background-image: none +} + +.form-select:disabled { + background-color: #e9ecef +} + +.form-select:-moz-focusring { + color: transparent; + text-shadow: 0 0 0 #212529 +} + +.form-select-sm { + padding-top: .25rem; + padding-bottom: .25rem; + padding-left: .5rem; + font-size: .875rem +} + +.form-select-lg { + padding-top: .5rem; + padding-bottom: .5rem; + padding-left: 1rem; + font-size: 1.25rem +} + +.form-check { + display: block; + min-height: 1.5rem; + padding-left: 1.5em; + margin-bottom: .125rem +} + +.form-check .form-check-input { + float: left; + margin-left: -1.5em +} + +.form-check-input { + width: 1em; + height: 1em; + margin-top: .25em; + vertical-align: top; + background-color: #fff; + background-repeat: no-repeat; + background-position: center; + background-size: contain; + border: 1px solid rgba(0, 0, 0, .25); + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-print-color-adjust: exact; + color-adjust: exact +} + +.form-check-input[type=checkbox] { + border-radius: .25em +} + +.form-check-input[type=radio] { + border-radius: 50% +} + +.form-check-input:active { + filter: brightness(90%) +} + +.form-check-input:focus { + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 .25rem rgba(13, 110, 253, .25) +} + +.form-check-input:checked { + background-color: #0d6efd; + border-color: #0d6efd +} + +.form-check-input:checked[type=checkbox] { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10l3 3l6-6'/%3e%3c/svg%3e") +} + +.form-check-input:checked[type=radio] { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='2' fill='%23fff'/%3e%3c/svg%3e") +} + +.form-check-input[type=checkbox]:indeterminate { + background-color: #0d6efd; + border-color: #0d6efd; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3e%3cpath fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='3' d='M6 10h8'/%3e%3c/svg%3e") +} + +.form-check-input:disabled { + pointer-events: none; + filter: none; + opacity: .5 +} + +.form-check-input:disabled ~ .form-check-label, .form-check-input[disabled] ~ .form-check-label { + opacity: .5 +} + +.form-switch { + padding-left: 2.5em +} + +.form-switch .form-check-input { + width: 2em; + margin-left: -2.5em; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba%280, 0, 0, 0.25%29'/%3e%3c/svg%3e"); + background-position: left center; + border-radius: 2em; + transition: background-position .15s ease-in-out +} + +@media (prefers-reduced-motion: reduce) { + .form-switch .form-check-input { + transition: none + } +} + +.form-switch .form-check-input:focus { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2386b7fe'/%3e%3c/svg%3e") +} + +.form-switch .form-check-input:checked { + background-position: right center; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3c/svg%3e") +} + +.form-check-inline { + display: inline-block; + margin-right: 1rem +} + +.btn-check { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none +} + +.btn-check:disabled + .btn, .btn-check[disabled] + .btn { + pointer-events: none; + filter: none; + opacity: .65 +} + +.form-range { + width: 100%; + height: 1.5rem; + padding: 0; + background-color: transparent; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none +} + +.form-range:focus { + outline: 0 +} + +.form-range:focus::-webkit-slider-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 .25rem rgba(13, 110, 253, .25) +} + +.form-range:focus::-moz-range-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 .25rem rgba(13, 110, 253, .25) +} + +.form-range::-moz-focus-outer { + border: 0 +} + +.form-range::-webkit-slider-thumb { + width: 1rem; + height: 1rem; + margin-top: -.25rem; + background-color: #0d6efd; + border: 0; + border-radius: 1rem; + -webkit-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out; + transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out; + -webkit-appearance: none; + appearance: none +} + +@media (prefers-reduced-motion: reduce) { + .form-range::-webkit-slider-thumb { + -webkit-transition: none; + transition: none + } +} + +.form-range::-webkit-slider-thumb:active { + background-color: #b6d4fe +} + +.form-range::-webkit-slider-runnable-track { + width: 100%; + height: .5rem; + color: transparent; + cursor: pointer; + background-color: #dee2e6; + border-color: transparent; + border-radius: 1rem +} + +.form-range::-moz-range-thumb { + width: 1rem; + height: 1rem; + background-color: #0d6efd; + border: 0; + border-radius: 1rem; + -moz-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out; + transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out; + -moz-appearance: none; + appearance: none +} + +@media (prefers-reduced-motion: reduce) { + .form-range::-moz-range-thumb { + -moz-transition: none; + transition: none + } +} + +.form-range::-moz-range-thumb:active { + background-color: #b6d4fe +} + +.form-range::-moz-range-track { + width: 100%; + height: .5rem; + color: transparent; + cursor: pointer; + background-color: #dee2e6; + border-color: transparent; + border-radius: 1rem +} + +.form-range:disabled { + pointer-events: none +} + +.form-range:disabled::-webkit-slider-thumb { + background-color: #adb5bd +} + +.form-range:disabled::-moz-range-thumb { + background-color: #adb5bd +} + +.form-floating { + position: relative +} + +.form-floating > .form-control, .form-floating > .form-select { + height: calc(3.5rem + 2px); + line-height: 1.25 +} + +.form-floating > label { + position: absolute; + top: 0; + left: 0; + height: 100%; + padding: 1rem .75rem; + pointer-events: none; + border: 1px solid transparent; + transform-origin: 0 0; + transition: opacity .1s ease-in-out, transform .1s ease-in-out +} + +@media (prefers-reduced-motion: reduce) { + .form-floating > label { + transition: none + } +} + +.form-floating > .form-control { + padding: 1rem .75rem +} + +.form-floating > .form-control::-moz-placeholder { + color: transparent +} + +.form-floating > .form-control::placeholder { + color: transparent +} + +.form-floating > .form-control:not(:-moz-placeholder-shown) { + padding-top: 1.625rem; + padding-bottom: .625rem +} + +.form-floating > .form-control:focus, .form-floating > .form-control:not(:placeholder-shown) { + padding-top: 1.625rem; + padding-bottom: .625rem +} + +.form-floating > .form-control:-webkit-autofill { + padding-top: 1.625rem; + padding-bottom: .625rem +} + +.form-floating > .form-select { + padding-top: 1.625rem; + padding-bottom: .625rem +} + +.form-floating > .form-control:not(:-moz-placeholder-shown) ~ label { + opacity: .65; + transform: scale(.85) translateY(-.5rem) translateX(.15rem) +} + +.form-floating > .form-control:focus ~ label, .form-floating > .form-control:not(:placeholder-shown) ~ label, .form-floating > .form-select ~ label { + opacity: .65; + transform: scale(.85) translateY(-.5rem) translateX(.15rem) +} + +.form-floating > .form-control:-webkit-autofill ~ label { + opacity: .65; + transform: scale(.85) translateY(-.5rem) translateX(.15rem) +} + +.input-group { + position: relative; + display: flex; + flex-wrap: wrap; + align-items: stretch; + width: 100% +} + +.input-group > .form-control, .input-group > .form-select { + position: relative; + flex: 1 1 auto; + width: 1%; + min-width: 0 +} + +.input-group > .form-control:focus, .input-group > .form-select:focus { + z-index: 3 +} + +.input-group .btn { + position: relative; + z-index: 2 +} + +.input-group .btn:focus { + z-index: 3 +} + +.input-group-text { + display: flex; + align-items: center; + padding: .375rem .75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + text-align: center; + white-space: nowrap; + background-color: #e9ecef; + border: 1px solid #ced4da; + border-radius: .25rem +} + +.input-group-lg > .btn, .input-group-lg > .form-control, .input-group-lg > .form-select, .input-group-lg > .input-group-text { + padding: .5rem 1rem; + font-size: 1.25rem; + border-radius: .3rem +} + +.input-group-sm > .btn, .input-group-sm > .form-control, .input-group-sm > .form-select, .input-group-sm > .input-group-text { + padding: .25rem .5rem; + font-size: .875rem; + border-radius: .2rem +} + +.input-group-lg > .form-select, .input-group-sm > .form-select { + padding-right: 3rem +} + +.input-group:not(.has-validation) > .dropdown-toggle:nth-last-child(n+3), .input-group:not(.has-validation) > :not(:last-child):not(.dropdown-toggle):not(.dropdown-menu) { + border-top-right-radius: 0; + border-bottom-right-radius: 0 +} + +.input-group.has-validation > .dropdown-toggle:nth-last-child(n+4), .input-group.has-validation > :nth-last-child(n+3):not(.dropdown-toggle):not(.dropdown-menu) { + border-top-right-radius: 0; + border-bottom-right-radius: 0 +} + +.input-group > :not(:first-child):not(.dropdown-menu):not(.valid-tooltip):not(.valid-feedback):not(.invalid-tooltip):not(.invalid-feedback) { + margin-left: -1px; + border-top-left-radius: 0; + border-bottom-left-radius: 0 +} + +.valid-feedback { + display: none; + width: 100%; + margin-top: .25rem; + font-size: .875em; + color: #198754 +} + +.valid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: .25rem .5rem; + margin-top: .1rem; + font-size: .875rem; + color: #fff; + background-color: rgba(25, 135, 84, .9); + border-radius: .25rem +} + +.is-valid ~ .valid-feedback, .is-valid ~ .valid-tooltip, .was-validated :valid ~ .valid-feedback, .was-validated :valid ~ .valid-tooltip { + display: block +} + +.form-control.is-valid, .was-validated .form-control:valid { + border-color: #198754; + padding-right: calc(1.5em + .75rem); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right calc(.375em + .1875rem) center; + background-size: calc(.75em + .375rem) calc(.75em + .375rem) +} + +.form-control.is-valid:focus, .was-validated .form-control:valid:focus { + border-color: #198754; + box-shadow: 0 0 0 .25rem rgba(25, 135, 84, .25) +} + +.was-validated textarea.form-control:valid, textarea.form-control.is-valid { + padding-right: calc(1.5em + .75rem); + background-position: top calc(.375em + .1875rem) right calc(.375em + .1875rem) +} + +.form-select.is-valid, .was-validated .form-select:valid { + border-color: #198754 +} + +.form-select.is-valid:not([multiple]):not([size]), .form-select.is-valid:not([multiple])[size="1"], .was-validated .form-select:valid:not([multiple]):not([size]), .was-validated .form-select:valid:not([multiple])[size="1"] { + padding-right: 4.125rem; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"), url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23198754' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"); + background-position: right .75rem center, center right 2.25rem; + background-size: 16px 12px, calc(.75em + .375rem) calc(.75em + .375rem) +} + +.form-select.is-valid:focus, .was-validated .form-select:valid:focus { + border-color: #198754; + box-shadow: 0 0 0 .25rem rgba(25, 135, 84, .25) +} + +.form-check-input.is-valid, .was-validated .form-check-input:valid { + border-color: #198754 +} + +.form-check-input.is-valid:checked, .was-validated .form-check-input:valid:checked { + background-color: #198754 +} + +.form-check-input.is-valid:focus, .was-validated .form-check-input:valid:focus { + box-shadow: 0 0 0 .25rem rgba(25, 135, 84, .25) +} + +.form-check-input.is-valid ~ .form-check-label, .was-validated .form-check-input:valid ~ .form-check-label { + color: #198754 +} + +.form-check-inline .form-check-input ~ .valid-feedback { + margin-left: .5em +} + +.input-group .form-control.is-valid, .input-group .form-select.is-valid, .was-validated .input-group .form-control:valid, .was-validated .input-group .form-select:valid { + z-index: 1 +} + +.input-group .form-control.is-valid:focus, .input-group .form-select.is-valid:focus, .was-validated .input-group .form-control:valid:focus, .was-validated .input-group .form-select:valid:focus { + z-index: 3 +} + +.invalid-feedback { + display: none; + width: 100%; + margin-top: .25rem; + font-size: .875em; + color: #dc3545 +} + +.invalid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: .25rem .5rem; + margin-top: .1rem; + font-size: .875rem; + color: #fff; + background-color: rgba(220, 53, 69, .9); + border-radius: .25rem +} + +.is-invalid ~ .invalid-feedback, .is-invalid ~ .invalid-tooltip, .was-validated :invalid ~ .invalid-feedback, .was-validated :invalid ~ .invalid-tooltip { + display: block +} + +.form-control.is-invalid, .was-validated .form-control:invalid { + border-color: #dc3545; + padding-right: calc(1.5em + .75rem); + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: right calc(.375em + .1875rem) center; + background-size: calc(.75em + .375rem) calc(.75em + .375rem) +} + +.form-control.is-invalid:focus, .was-validated .form-control:invalid:focus { + border-color: #dc3545; + box-shadow: 0 0 0 .25rem rgba(220, 53, 69, .25) +} + +.was-validated textarea.form-control:invalid, textarea.form-control.is-invalid { + padding-right: calc(1.5em + .75rem); + background-position: top calc(.375em + .1875rem) right calc(.375em + .1875rem) +} + +.form-select.is-invalid, .was-validated .form-select:invalid { + border-color: #dc3545 +} + +.form-select.is-invalid:not([multiple]):not([size]), .form-select.is-invalid:not([multiple])[size="1"], .was-validated .form-select:invalid:not([multiple]):not([size]), .was-validated .form-select:invalid:not([multiple])[size="1"] { + padding-right: 4.125rem; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e"), url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='%23dc3545'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e"); + background-position: right .75rem center, center right 2.25rem; + background-size: 16px 12px, calc(.75em + .375rem) calc(.75em + .375rem) +} + +.form-select.is-invalid:focus, .was-validated .form-select:invalid:focus { + border-color: #dc3545; + box-shadow: 0 0 0 .25rem rgba(220, 53, 69, .25) +} + +.form-check-input.is-invalid, .was-validated .form-check-input:invalid { + border-color: #dc3545 +} + +.form-check-input.is-invalid:checked, .was-validated .form-check-input:invalid:checked { + background-color: #dc3545 +} + +.form-check-input.is-invalid:focus, .was-validated .form-check-input:invalid:focus { + box-shadow: 0 0 0 .25rem rgba(220, 53, 69, .25) +} + +.form-check-input.is-invalid ~ .form-check-label, .was-validated .form-check-input:invalid ~ .form-check-label { + color: #dc3545 +} + +.form-check-inline .form-check-input ~ .invalid-feedback { + margin-left: .5em +} + +.input-group .form-control.is-invalid, .input-group .form-select.is-invalid, .was-validated .input-group .form-control:invalid, .was-validated .input-group .form-select:invalid { + z-index: 2 +} + +.input-group .form-control.is-invalid:focus, .input-group .form-select.is-invalid:focus, .was-validated .input-group .form-control:invalid:focus, .was-validated .input-group .form-select:invalid:focus { + z-index: 3 +} + +.btn { + display: inline-block; + font-weight: 400; + line-height: 1.5; + color: #212529; + text-align: center; + text-decoration: none; + vertical-align: middle; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + background-color: transparent; + border: 1px solid transparent; + padding: .375rem .75rem; + font-size: 1rem; + border-radius: .25rem; + transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out +} + +@media (prefers-reduced-motion: reduce) { + .btn { + transition: none + } +} + +.btn:hover { + color: #212529 +} + +.btn-check:focus + .btn, .btn:focus { + outline: 0; + box-shadow: 0 0 0 .25rem rgba(13, 110, 253, .25) +} + +.btn.disabled, .btn:disabled, fieldset:disabled .btn { + pointer-events: none; + opacity: .65 +} + +.btn-primary { + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd +} + +.btn-primary:hover { + color: #fff; + background-color: #0b5ed7; + border-color: #0a58ca +} + +.btn-check:focus + .btn-primary, .btn-primary:focus { + color: #fff; + background-color: #0b5ed7; + border-color: #0a58ca; + box-shadow: 0 0 0 .25rem rgba(49, 132, 253, .5) +} + +.btn-check:active + .btn-primary, .btn-check:checked + .btn-primary, .btn-primary.active, .btn-primary:active, .show > .btn-primary.dropdown-toggle { + color: #fff; + background-color: #0a58ca; + border-color: #0a53be +} + +.btn-check:active + .btn-primary:focus, .btn-check:checked + .btn-primary:focus, .btn-primary.active:focus, .btn-primary:active:focus, .show > .btn-primary.dropdown-toggle:focus { + box-shadow: 0 0 0 .25rem rgba(49, 132, 253, .5) +} + +.btn-primary.disabled, .btn-primary:disabled { + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd +} + +.btn-secondary { + color: #fff; + background-color: #6c757d; + border-color: #6c757d +} + +.btn-secondary:hover { + color: #fff; + background-color: #5c636a; + border-color: #565e64 +} + +.btn-check:focus + .btn-secondary, .btn-secondary:focus { + color: #fff; + background-color: #5c636a; + border-color: #565e64; + box-shadow: 0 0 0 .25rem rgba(130, 138, 145, .5) +} + +.btn-check:active + .btn-secondary, .btn-check:checked + .btn-secondary, .btn-secondary.active, .btn-secondary:active, .show > .btn-secondary.dropdown-toggle { + color: #fff; + background-color: #565e64; + border-color: #51585e +} + +.btn-check:active + .btn-secondary:focus, .btn-check:checked + .btn-secondary:focus, .btn-secondary.active:focus, .btn-secondary:active:focus, .show > .btn-secondary.dropdown-toggle:focus { + box-shadow: 0 0 0 .25rem rgba(130, 138, 145, .5) +} + +.btn-secondary.disabled, .btn-secondary:disabled { + color: #fff; + background-color: #6c757d; + border-color: #6c757d +} + +.btn-success { + color: #fff; + background-color: #198754; + border-color: #198754 +} + +.btn-success:hover { + color: #fff; + background-color: #157347; + border-color: #146c43 +} + +.btn-check:focus + .btn-success, .btn-success:focus { + color: #fff; + background-color: #157347; + border-color: #146c43; + box-shadow: 0 0 0 .25rem rgba(60, 153, 110, .5) +} + +.btn-check:active + .btn-success, .btn-check:checked + .btn-success, .btn-success.active, .btn-success:active, .show > .btn-success.dropdown-toggle { + color: #fff; + background-color: #146c43; + border-color: #13653f +} + +.btn-check:active + .btn-success:focus, .btn-check:checked + .btn-success:focus, .btn-success.active:focus, .btn-success:active:focus, .show > .btn-success.dropdown-toggle:focus { + box-shadow: 0 0 0 .25rem rgba(60, 153, 110, .5) +} + +.btn-success.disabled, .btn-success:disabled { + color: #fff; + background-color: #198754; + border-color: #198754 +} + +.btn-info { + color: #000; + background-color: #0dcaf0; + border-color: #0dcaf0 +} + +.btn-info:hover { + color: #000; + background-color: #31d2f2; + border-color: #25cff2 +} + +.btn-check:focus + .btn-info, .btn-info:focus { + color: #000; + background-color: #31d2f2; + border-color: #25cff2; + box-shadow: 0 0 0 .25rem rgba(11, 172, 204, .5) +} + +.btn-check:active + .btn-info, .btn-check:checked + .btn-info, .btn-info.active, .btn-info:active, .show > .btn-info.dropdown-toggle { + color: #000; + background-color: #3dd5f3; + border-color: #25cff2 +} + +.btn-check:active + .btn-info:focus, .btn-check:checked + .btn-info:focus, .btn-info.active:focus, .btn-info:active:focus, .show > .btn-info.dropdown-toggle:focus { + box-shadow: 0 0 0 .25rem rgba(11, 172, 204, .5) +} + +.btn-info.disabled, .btn-info:disabled { + color: #000; + background-color: #0dcaf0; + border-color: #0dcaf0 +} + +.btn-warning { + color: #000; + background-color: #ffc107; + border-color: #ffc107 +} + +.btn-warning:hover { + color: #000; + background-color: #ffca2c; + border-color: #ffc720 +} + +.btn-check:focus + .btn-warning, .btn-warning:focus { + color: #000; + background-color: #ffca2c; + border-color: #ffc720; + box-shadow: 0 0 0 .25rem rgba(217, 164, 6, .5) +} + +.btn-check:active + .btn-warning, .btn-check:checked + .btn-warning, .btn-warning.active, .btn-warning:active, .show > .btn-warning.dropdown-toggle { + color: #000; + background-color: #ffcd39; + border-color: #ffc720 +} + +.btn-check:active + .btn-warning:focus, .btn-check:checked + .btn-warning:focus, .btn-warning.active:focus, .btn-warning:active:focus, .show > .btn-warning.dropdown-toggle:focus { + box-shadow: 0 0 0 .25rem rgba(217, 164, 6, .5) +} + +.btn-warning.disabled, .btn-warning:disabled { + color: #000; + background-color: #ffc107; + border-color: #ffc107 +} + +.btn-danger { + color: #fff; + background-color: #dc3545; + border-color: #dc3545 +} + +.btn-danger:hover { + color: #fff; + background-color: #bb2d3b; + border-color: #b02a37 +} + +.btn-check:focus + .btn-danger, .btn-danger:focus { + color: #fff; + background-color: #bb2d3b; + border-color: #b02a37; + box-shadow: 0 0 0 .25rem rgba(225, 83, 97, .5) +} + +.btn-check:active + .btn-danger, .btn-check:checked + .btn-danger, .btn-danger.active, .btn-danger:active, .show > .btn-danger.dropdown-toggle { + color: #fff; + background-color: #b02a37; + border-color: #a52834 +} + +.btn-check:active + .btn-danger:focus, .btn-check:checked + .btn-danger:focus, .btn-danger.active:focus, .btn-danger:active:focus, .show > .btn-danger.dropdown-toggle:focus { + box-shadow: 0 0 0 .25rem rgba(225, 83, 97, .5) +} + +.btn-danger.disabled, .btn-danger:disabled { + color: #fff; + background-color: #dc3545; + border-color: #dc3545 +} + +.btn-light { + color: #000; + background-color: #f8f9fa; + border-color: #f8f9fa +} + +.btn-light:hover { + color: #000; + background-color: #f9fafb; + border-color: #f9fafb +} + +.btn-check:focus + .btn-light, .btn-light:focus { + color: #000; + background-color: #f9fafb; + border-color: #f9fafb; + box-shadow: 0 0 0 .25rem rgba(211, 212, 213, .5) +} + +.btn-check:active + .btn-light, .btn-check:checked + .btn-light, .btn-light.active, .btn-light:active, .show > .btn-light.dropdown-toggle { + color: #000; + background-color: #f9fafb; + border-color: #f9fafb +} + +.btn-check:active + .btn-light:focus, .btn-check:checked + .btn-light:focus, .btn-light.active:focus, .btn-light:active:focus, .show > .btn-light.dropdown-toggle:focus { + box-shadow: 0 0 0 .25rem rgba(211, 212, 213, .5) +} + +.btn-light.disabled, .btn-light:disabled { + color: #000; + background-color: #f8f9fa; + border-color: #f8f9fa +} + +.btn-dark { + color: #fff; + background-color: #212529; + border-color: #212529 +} + +.btn-dark:hover { + color: #fff; + background-color: #1c1f23; + border-color: #1a1e21 +} + +.btn-check:focus + .btn-dark, .btn-dark:focus { + color: #fff; + background-color: #1c1f23; + border-color: #1a1e21; + box-shadow: 0 0 0 .25rem rgba(66, 70, 73, .5) +} + +.btn-check:active + .btn-dark, .btn-check:checked + .btn-dark, .btn-dark.active, .btn-dark:active, .show > .btn-dark.dropdown-toggle { + color: #fff; + background-color: #1a1e21; + border-color: #191c1f +} + +.btn-check:active + .btn-dark:focus, .btn-check:checked + .btn-dark:focus, .btn-dark.active:focus, .btn-dark:active:focus, .show > .btn-dark.dropdown-toggle:focus { + box-shadow: 0 0 0 .25rem rgba(66, 70, 73, .5) +} + +.btn-dark.disabled, .btn-dark:disabled { + color: #fff; + background-color: #212529; + border-color: #212529 +} + +.btn-outline-primary { + color: #0d6efd; + border-color: #0d6efd +} + +.btn-outline-primary:hover { + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd +} + +.btn-check:focus + .btn-outline-primary, .btn-outline-primary:focus { + box-shadow: 0 0 0 .25rem rgba(13, 110, 253, .5) +} + +.btn-check:active + .btn-outline-primary, .btn-check:checked + .btn-outline-primary, .btn-outline-primary.active, .btn-outline-primary.dropdown-toggle.show, .btn-outline-primary:active { + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd +} + +.btn-check:active + .btn-outline-primary:focus, .btn-check:checked + .btn-outline-primary:focus, .btn-outline-primary.active:focus, .btn-outline-primary.dropdown-toggle.show:focus, .btn-outline-primary:active:focus { + box-shadow: 0 0 0 .25rem rgba(13, 110, 253, .5) +} + +.btn-outline-primary.disabled, .btn-outline-primary:disabled { + color: #0d6efd; + background-color: transparent +} + +.btn-outline-secondary { + color: #6c757d; + border-color: #6c757d +} + +.btn-outline-secondary:hover { + color: #fff; + background-color: #6c757d; + border-color: #6c757d +} + +.btn-check:focus + .btn-outline-secondary, .btn-outline-secondary:focus { + box-shadow: 0 0 0 .25rem rgba(108, 117, 125, .5) +} + +.btn-check:active + .btn-outline-secondary, .btn-check:checked + .btn-outline-secondary, .btn-outline-secondary.active, .btn-outline-secondary.dropdown-toggle.show, .btn-outline-secondary:active { + color: #fff; + background-color: #6c757d; + border-color: #6c757d +} + +.btn-check:active + .btn-outline-secondary:focus, .btn-check:checked + .btn-outline-secondary:focus, .btn-outline-secondary.active:focus, .btn-outline-secondary.dropdown-toggle.show:focus, .btn-outline-secondary:active:focus { + box-shadow: 0 0 0 .25rem rgba(108, 117, 125, .5) +} + +.btn-outline-secondary.disabled, .btn-outline-secondary:disabled { + color: #6c757d; + background-color: transparent +} + +.btn-outline-success { + color: #198754; + border-color: #198754 +} + +.btn-outline-success:hover { + color: #fff; + background-color: #198754; + border-color: #198754 +} + +.btn-check:focus + .btn-outline-success, .btn-outline-success:focus { + box-shadow: 0 0 0 .25rem rgba(25, 135, 84, .5) +} + +.btn-check:active + .btn-outline-success, .btn-check:checked + .btn-outline-success, .btn-outline-success.active, .btn-outline-success.dropdown-toggle.show, .btn-outline-success:active { + color: #fff; + background-color: #198754; + border-color: #198754 +} + +.btn-check:active + .btn-outline-success:focus, .btn-check:checked + .btn-outline-success:focus, .btn-outline-success.active:focus, .btn-outline-success.dropdown-toggle.show:focus, .btn-outline-success:active:focus { + box-shadow: 0 0 0 .25rem rgba(25, 135, 84, .5) +} + +.btn-outline-success.disabled, .btn-outline-success:disabled { + color: #198754; + background-color: transparent +} + +.btn-outline-info { + color: #0dcaf0; + border-color: #0dcaf0 +} + +.btn-outline-info:hover { + color: #000; + background-color: #0dcaf0; + border-color: #0dcaf0 +} + +.btn-check:focus + .btn-outline-info, .btn-outline-info:focus { + box-shadow: 0 0 0 .25rem rgba(13, 202, 240, .5) +} + +.btn-check:active + .btn-outline-info, .btn-check:checked + .btn-outline-info, .btn-outline-info.active, .btn-outline-info.dropdown-toggle.show, .btn-outline-info:active { + color: #000; + background-color: #0dcaf0; + border-color: #0dcaf0 +} + +.btn-check:active + .btn-outline-info:focus, .btn-check:checked + .btn-outline-info:focus, .btn-outline-info.active:focus, .btn-outline-info.dropdown-toggle.show:focus, .btn-outline-info:active:focus { + box-shadow: 0 0 0 .25rem rgba(13, 202, 240, .5) +} + +.btn-outline-info.disabled, .btn-outline-info:disabled { + color: #0dcaf0; + background-color: transparent +} + +.btn-outline-warning { + color: #ffc107; + border-color: #ffc107 +} + +.btn-outline-warning:hover { + color: #000; + background-color: #ffc107; + border-color: #ffc107 +} + +.btn-check:focus + .btn-outline-warning, .btn-outline-warning:focus { + box-shadow: 0 0 0 .25rem rgba(255, 193, 7, .5) +} + +.btn-check:active + .btn-outline-warning, .btn-check:checked + .btn-outline-warning, .btn-outline-warning.active, .btn-outline-warning.dropdown-toggle.show, .btn-outline-warning:active { + color: #000; + background-color: #ffc107; + border-color: #ffc107 +} + +.btn-check:active + .btn-outline-warning:focus, .btn-check:checked + .btn-outline-warning:focus, .btn-outline-warning.active:focus, .btn-outline-warning.dropdown-toggle.show:focus, .btn-outline-warning:active:focus { + box-shadow: 0 0 0 .25rem rgba(255, 193, 7, .5) +} + +.btn-outline-warning.disabled, .btn-outline-warning:disabled { + color: #ffc107; + background-color: transparent +} + +.btn-outline-danger { + color: #dc3545; + border-color: #dc3545 +} + +.btn-outline-danger:hover { + color: #fff; + background-color: #dc3545; + border-color: #dc3545 +} + +.btn-check:focus + .btn-outline-danger, .btn-outline-danger:focus { + box-shadow: 0 0 0 .25rem rgba(220, 53, 69, .5) +} + +.btn-check:active + .btn-outline-danger, .btn-check:checked + .btn-outline-danger, .btn-outline-danger.active, .btn-outline-danger.dropdown-toggle.show, .btn-outline-danger:active { + color: #fff; + background-color: #dc3545; + border-color: #dc3545 +} + +.btn-check:active + .btn-outline-danger:focus, .btn-check:checked + .btn-outline-danger:focus, .btn-outline-danger.active:focus, .btn-outline-danger.dropdown-toggle.show:focus, .btn-outline-danger:active:focus { + box-shadow: 0 0 0 .25rem rgba(220, 53, 69, .5) +} + +.btn-outline-danger.disabled, .btn-outline-danger:disabled { + color: #dc3545; + background-color: transparent +} + +.btn-outline-light { + color: #f8f9fa; + border-color: #f8f9fa +} + +.btn-outline-light:hover { + color: #000; + background-color: #f8f9fa; + border-color: #f8f9fa +} + +.btn-check:focus + .btn-outline-light, .btn-outline-light:focus { + box-shadow: 0 0 0 .25rem rgba(248, 249, 250, .5) +} + +.btn-check:active + .btn-outline-light, .btn-check:checked + .btn-outline-light, .btn-outline-light.active, .btn-outline-light.dropdown-toggle.show, .btn-outline-light:active { + color: #000; + background-color: #f8f9fa; + border-color: #f8f9fa +} + +.btn-check:active + .btn-outline-light:focus, .btn-check:checked + .btn-outline-light:focus, .btn-outline-light.active:focus, .btn-outline-light.dropdown-toggle.show:focus, .btn-outline-light:active:focus { + box-shadow: 0 0 0 .25rem rgba(248, 249, 250, .5) +} + +.btn-outline-light.disabled, .btn-outline-light:disabled { + color: #f8f9fa; + background-color: transparent +} + +.btn-outline-dark { + color: #212529; + border-color: #212529 +} + +.btn-outline-dark:hover { + color: #fff; + background-color: #212529; + border-color: #212529 +} + +.btn-check:focus + .btn-outline-dark, .btn-outline-dark:focus { + box-shadow: 0 0 0 .25rem rgba(33, 37, 41, .5) +} + +.btn-check:active + .btn-outline-dark, .btn-check:checked + .btn-outline-dark, .btn-outline-dark.active, .btn-outline-dark.dropdown-toggle.show, .btn-outline-dark:active { + color: #fff; + background-color: #212529; + border-color: #212529 +} + +.btn-check:active + .btn-outline-dark:focus, .btn-check:checked + .btn-outline-dark:focus, .btn-outline-dark.active:focus, .btn-outline-dark.dropdown-toggle.show:focus, .btn-outline-dark:active:focus { + box-shadow: 0 0 0 .25rem rgba(33, 37, 41, .5) +} + +.btn-outline-dark.disabled, .btn-outline-dark:disabled { + color: #212529; + background-color: transparent +} + +.btn-link { + font-weight: 400; + color: #0d6efd; + text-decoration: underline +} + +.btn-link:hover { + color: #0a58ca +} + +.btn-link.disabled, .btn-link:disabled { + color: #6c757d +} + +.btn-group-lg > .btn, .btn-lg { + padding: .5rem 1rem; + font-size: 1.25rem; + border-radius: .3rem +} + +.btn-group-sm > .btn, .btn-sm { + padding: .25rem .5rem; + font-size: .875rem; + border-radius: .2rem +} + +.fade { + transition: opacity .15s linear +} + +@media (prefers-reduced-motion: reduce) { + .fade { + transition: none + } +} + +.fade:not(.show) { + opacity: 0 +} + +.collapse:not(.show) { + display: none +} + +.collapsing { + height: 0; + overflow: hidden; + transition: height .35s ease +} + +@media (prefers-reduced-motion: reduce) { + .collapsing { + transition: none + } +} + +.dropdown, .dropend, .dropstart, .dropup { + position: relative +} + +.dropdown-toggle { + white-space: nowrap +} + +.dropdown-toggle::after { + display: inline-block; + margin-left: .255em; + vertical-align: .255em; + content: ""; + border-top: .3em solid; + border-right: .3em solid transparent; + border-bottom: 0; + border-left: .3em solid transparent +} + +.dropdown-toggle:empty::after { + margin-left: 0 +} + +.dropdown-menu { + position: absolute; + z-index: 1000; + display: none; + min-width: 10rem; + padding: .5rem 0; + margin: 0; + font-size: 1rem; + color: #212529; + text-align: left; + list-style: none; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, .15); + border-radius: .25rem +} + +.dropdown-menu[data-bs-popper] { + top: 100%; + left: 0; + margin-top: .125rem +} + +.dropdown-menu-start { + --bs-position: start +} + +.dropdown-menu-start[data-bs-popper] { + right: auto; + left: 0 +} + +.dropdown-menu-end { + --bs-position: end +} + +.dropdown-menu-end[data-bs-popper] { + right: 0; + left: auto +} + +@media (min-width: 576px) { + .dropdown-menu-sm-start { + --bs-position: start + } + + .dropdown-menu-sm-start[data-bs-popper] { + right: auto; + left: 0 + } + + .dropdown-menu-sm-end { + --bs-position: end + } + + .dropdown-menu-sm-end[data-bs-popper] { + right: 0; + left: auto + } +} + +@media (min-width: 768px) { + .dropdown-menu-md-start { + --bs-position: start + } + + .dropdown-menu-md-start[data-bs-popper] { + right: auto; + left: 0 + } + + .dropdown-menu-md-end { + --bs-position: end + } + + .dropdown-menu-md-end[data-bs-popper] { + right: 0; + left: auto + } +} + +@media (min-width: 992px) { + .dropdown-menu-lg-start { + --bs-position: start + } + + .dropdown-menu-lg-start[data-bs-popper] { + right: auto; + left: 0 + } + + .dropdown-menu-lg-end { + --bs-position: end + } + + .dropdown-menu-lg-end[data-bs-popper] { + right: 0; + left: auto + } +} + +@media (min-width: 1200px) { + .dropdown-menu-xl-start { + --bs-position: start + } + + .dropdown-menu-xl-start[data-bs-popper] { + right: auto; + left: 0 + } + + .dropdown-menu-xl-end { + --bs-position: end + } + + .dropdown-menu-xl-end[data-bs-popper] { + right: 0; + left: auto + } +} + +@media (min-width: 1400px) { + .dropdown-menu-xxl-start { + --bs-position: start + } + + .dropdown-menu-xxl-start[data-bs-popper] { + right: auto; + left: 0 + } + + .dropdown-menu-xxl-end { + --bs-position: end + } + + .dropdown-menu-xxl-end[data-bs-popper] { + right: 0; + left: auto + } +} + +.dropup .dropdown-menu[data-bs-popper] { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: .125rem +} + +.dropup .dropdown-toggle::after { + display: inline-block; + margin-left: .255em; + vertical-align: .255em; + content: ""; + border-top: 0; + border-right: .3em solid transparent; + border-bottom: .3em solid; + border-left: .3em solid transparent +} + +.dropup .dropdown-toggle:empty::after { + margin-left: 0 +} + +.dropend .dropdown-menu[data-bs-popper] { + top: 0; + right: auto; + left: 100%; + margin-top: 0; + margin-left: .125rem +} + +.dropend .dropdown-toggle::after { + display: inline-block; + margin-left: .255em; + vertical-align: .255em; + content: ""; + border-top: .3em solid transparent; + border-right: 0; + border-bottom: .3em solid transparent; + border-left: .3em solid +} + +.dropend .dropdown-toggle:empty::after { + margin-left: 0 +} + +.dropend .dropdown-toggle::after { + vertical-align: 0 +} + +.dropstart .dropdown-menu[data-bs-popper] { + top: 0; + right: 100%; + left: auto; + margin-top: 0; + margin-right: .125rem +} + +.dropstart .dropdown-toggle::after { + display: inline-block; + margin-left: .255em; + vertical-align: .255em; + content: "" +} + +.dropstart .dropdown-toggle::after { + display: none +} + +.dropstart .dropdown-toggle::before { + display: inline-block; + margin-right: .255em; + vertical-align: .255em; + content: ""; + border-top: .3em solid transparent; + border-right: .3em solid; + border-bottom: .3em solid transparent +} + +.dropstart .dropdown-toggle:empty::after { + margin-left: 0 +} + +.dropstart .dropdown-toggle::before { + vertical-align: 0 +} + +.dropdown-divider { + height: 0; + margin: .5rem 0; + overflow: hidden; + border-top: 1px solid rgba(0, 0, 0, .15) +} + +.dropdown-item { + display: block; + width: 100%; + padding: .25rem 1rem; + clear: both; + font-weight: 400; + color: #212529; + text-align: inherit; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border: 0 +} + +.dropdown-item:focus, .dropdown-item:hover { + color: #1e2125; + background-color: #e9ecef +} + +.dropdown-item.active, .dropdown-item:active { + color: #fff; + text-decoration: none; + background-color: #0d6efd +} + +.dropdown-item.disabled, .dropdown-item:disabled { + color: #adb5bd; + pointer-events: none; + background-color: transparent +} + +.dropdown-menu.show { + display: block +} + +.dropdown-header { + display: block; + padding: .5rem 1rem; + margin-bottom: 0; + font-size: .875rem; + color: #6c757d; + white-space: nowrap +} + +.dropdown-item-text { + display: block; + padding: .25rem 1rem; + color: #212529 +} + +.dropdown-menu-dark { + color: #dee2e6; + background-color: #343a40; + border-color: rgba(0, 0, 0, .15) +} + +.dropdown-menu-dark .dropdown-item { + color: #dee2e6 +} + +.dropdown-menu-dark .dropdown-item:focus, .dropdown-menu-dark .dropdown-item:hover { + color: #fff; + background-color: rgba(255, 255, 255, .15) +} + +.dropdown-menu-dark .dropdown-item.active, .dropdown-menu-dark .dropdown-item:active { + color: #fff; + background-color: #0d6efd +} + +.dropdown-menu-dark .dropdown-item.disabled, .dropdown-menu-dark .dropdown-item:disabled { + color: #adb5bd +} + +.dropdown-menu-dark .dropdown-divider { + border-color: rgba(0, 0, 0, .15) +} + +.dropdown-menu-dark .dropdown-item-text { + color: #dee2e6 +} + +.dropdown-menu-dark .dropdown-header { + color: #adb5bd +} + +.btn-group, .btn-group-vertical { + position: relative; + display: inline-flex; + vertical-align: middle +} + +.btn-group-vertical > .btn, .btn-group > .btn { + position: relative; + flex: 1 1 auto +} + +.btn-group-vertical > .btn-check:checked + .btn, .btn-group-vertical > .btn-check:focus + .btn, .btn-group-vertical > .btn.active, .btn-group-vertical > .btn:active, .btn-group-vertical > .btn:focus, .btn-group-vertical > .btn:hover, .btn-group > .btn-check:checked + .btn, .btn-group > .btn-check:focus + .btn, .btn-group > .btn.active, .btn-group > .btn:active, .btn-group > .btn:focus, .btn-group > .btn:hover { + z-index: 1 +} + +.btn-toolbar { + display: flex; + flex-wrap: wrap; + justify-content: flex-start +} + +.btn-toolbar .input-group { + width: auto +} + +.btn-group > .btn-group:not(:first-child), .btn-group > .btn:not(:first-child) { + margin-left: -1px +} + +.btn-group > .btn-group:not(:last-child) > .btn, .btn-group > .btn:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0 +} + +.btn-group > .btn-group:not(:first-child) > .btn, .btn-group > .btn:nth-child(n+3), .btn-group > :not(.btn-check) + .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0 +} + +.dropdown-toggle-split { + padding-right: .5625rem; + padding-left: .5625rem +} + +.dropdown-toggle-split::after, .dropend .dropdown-toggle-split::after, .dropup .dropdown-toggle-split::after { + margin-left: 0 +} + +.dropstart .dropdown-toggle-split::before { + margin-right: 0 +} + +.btn-group-sm > .btn + .dropdown-toggle-split, .btn-sm + .dropdown-toggle-split { + padding-right: .375rem; + padding-left: .375rem +} + +.btn-group-lg > .btn + .dropdown-toggle-split, .btn-lg + .dropdown-toggle-split { + padding-right: .75rem; + padding-left: .75rem +} + +.btn-group-vertical { + flex-direction: column; + align-items: flex-start; + justify-content: center +} + +.btn-group-vertical > .btn, .btn-group-vertical > .btn-group { + width: 100% +} + +.btn-group-vertical > .btn-group:not(:first-child), .btn-group-vertical > .btn:not(:first-child) { + margin-top: -1px +} + +.btn-group-vertical > .btn-group:not(:last-child) > .btn, .btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0 +} + +.btn-group-vertical > .btn-group:not(:first-child) > .btn, .btn-group-vertical > .btn ~ .btn { + border-top-left-radius: 0; + border-top-right-radius: 0 +} + +.nav { + display: flex; + flex-wrap: wrap; + padding-left: 0; + margin-bottom: 0; + list-style: none +} + +.nav-link { + display: block; + padding: .5rem 1rem; + color: #0d6efd; + text-decoration: none; + transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out +} + +@media (prefers-reduced-motion: reduce) { + .nav-link { + transition: none + } +} + +.nav-link:focus, .nav-link:hover { + color: #0a58ca +} + +.nav-link.disabled { + color: #6c757d; + pointer-events: none; + cursor: default +} + +.nav-tabs { + border-bottom: 1px solid #dee2e6 +} + +.nav-tabs .nav-link { + margin-bottom: -1px; + background: 0 0; + border: 1px solid transparent; + border-top-left-radius: .25rem; + border-top-right-radius: .25rem +} + +.nav-tabs .nav-link:focus, .nav-tabs .nav-link:hover { + border-color: #e9ecef #e9ecef #dee2e6; + isolation: isolate +} + +.nav-tabs .nav-link.disabled { + color: #6c757d; + background-color: transparent; + border-color: transparent +} + +.nav-tabs .nav-item.show .nav-link, .nav-tabs .nav-link.active { + color: #495057; + background-color: #fff; + border-color: #dee2e6 #dee2e6 #fff +} + +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0 +} + +.nav-pills .nav-link { + background: 0 0; + border: 0; + border-radius: .25rem +} + +.nav-pills .nav-link.active, .nav-pills .show > .nav-link { + color: #fff; + background-color: #0d6efd +} + +.nav-fill .nav-item, .nav-fill > .nav-link { + flex: 1 1 auto; + text-align: center +} + +.nav-justified .nav-item, .nav-justified > .nav-link { + flex-basis: 0; + flex-grow: 1; + text-align: center +} + +.nav-fill .nav-item .nav-link, .nav-justified .nav-item .nav-link { + width: 100% +} + +.tab-content > .tab-pane { + display: none +} + +.tab-content > .active { + display: block +} + +.navbar { + position: relative; + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: space-between; + padding-top: .5rem; + padding-bottom: .5rem +} + +.navbar > .container, .navbar > .container-fluid, .navbar > .container-lg, .navbar > .container-md, .navbar > .container-sm, .navbar > .container-xl, .navbar > .container-xxl { + display: flex; + flex-wrap: inherit; + align-items: center; + justify-content: space-between +} + +.navbar-brand { + padding-top: .3125rem; + padding-bottom: .3125rem; + margin-right: 1rem; + font-size: 1.25rem; + text-decoration: none; + white-space: nowrap +} + +.navbar-nav { + display: flex; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; + list-style: none +} + +.navbar-nav .nav-link { + padding-right: 0; + padding-left: 0 +} + +.navbar-nav .dropdown-menu { + position: static +} + +.navbar-text { + padding-top: .5rem; + padding-bottom: .5rem +} + +.navbar-collapse { + flex-basis: 100%; + flex-grow: 1; + align-items: center +} + +.navbar-toggler { + padding: .25rem .75rem; + font-size: 1.25rem; + line-height: 1; + background-color: transparent; + border: 1px solid transparent; + border-radius: .25rem; + transition: box-shadow .15s ease-in-out +} + +@media (prefers-reduced-motion: reduce) { + .navbar-toggler { + transition: none + } +} + +.navbar-toggler:hover { + text-decoration: none +} + +.navbar-toggler:focus { + text-decoration: none; + outline: 0; + box-shadow: 0 0 0 .25rem +} + +.navbar-toggler-icon { + display: inline-block; + width: 1.5em; + height: 1.5em; + vertical-align: middle; + background-repeat: no-repeat; + background-position: center; + background-size: 100% +} + +.navbar-nav-scroll { + max-height: var(--bs-scroll-height, 75vh); + overflow-y: auto +} + +@media (min-width: 576px) { + .navbar-expand-sm { + flex-wrap: nowrap; + justify-content: flex-start + } + + .navbar-expand-sm .navbar-nav { + flex-direction: row + } + + .navbar-expand-sm .navbar-nav .dropdown-menu { + position: absolute + } + + .navbar-expand-sm .navbar-nav .nav-link { + padding-right: .5rem; + padding-left: .5rem + } + + .navbar-expand-sm .navbar-nav-scroll { + overflow: visible + } + + .navbar-expand-sm .navbar-collapse { + display: flex !important; + flex-basis: auto + } + + .navbar-expand-sm .navbar-toggler { + display: none + } +} + +@media (min-width: 768px) { + .navbar-expand-md { + flex-wrap: nowrap; + justify-content: flex-start + } + + .navbar-expand-md .navbar-nav { + flex-direction: row + } + + .navbar-expand-md .navbar-nav .dropdown-menu { + position: absolute + } + + .navbar-expand-md .navbar-nav .nav-link { + padding-right: .5rem; + padding-left: .5rem + } + + .navbar-expand-md .navbar-nav-scroll { + overflow: visible + } + + .navbar-expand-md .navbar-collapse { + display: flex !important; + flex-basis: auto + } + + .navbar-expand-md .navbar-toggler { + display: none + } +} + +@media (min-width: 992px) { + .navbar-expand-lg { + flex-wrap: nowrap; + justify-content: flex-start + } + + .navbar-expand-lg .navbar-nav { + flex-direction: row + } + + .navbar-expand-lg .navbar-nav .dropdown-menu { + position: absolute + } + + .navbar-expand-lg .navbar-nav .nav-link { + padding-right: .5rem; + padding-left: .5rem + } + + .navbar-expand-lg .navbar-nav-scroll { + overflow: visible + } + + .navbar-expand-lg .navbar-collapse { + display: flex !important; + flex-basis: auto + } + + .navbar-expand-lg .navbar-toggler { + display: none + } +} + +@media (min-width: 1200px) { + .navbar-expand-xl { + flex-wrap: nowrap; + justify-content: flex-start + } + + .navbar-expand-xl .navbar-nav { + flex-direction: row + } + + .navbar-expand-xl .navbar-nav .dropdown-menu { + position: absolute + } + + .navbar-expand-xl .navbar-nav .nav-link { + padding-right: .5rem; + padding-left: .5rem + } + + .navbar-expand-xl .navbar-nav-scroll { + overflow: visible + } + + .navbar-expand-xl .navbar-collapse { + display: flex !important; + flex-basis: auto + } + + .navbar-expand-xl .navbar-toggler { + display: none + } +} + +@media (min-width: 1400px) { + .navbar-expand-xxl { + flex-wrap: nowrap; + justify-content: flex-start + } + + .navbar-expand-xxl .navbar-nav { + flex-direction: row + } + + .navbar-expand-xxl .navbar-nav .dropdown-menu { + position: absolute + } + + .navbar-expand-xxl .navbar-nav .nav-link { + padding-right: .5rem; + padding-left: .5rem + } + + .navbar-expand-xxl .navbar-nav-scroll { + overflow: visible + } + + .navbar-expand-xxl .navbar-collapse { + display: flex !important; + flex-basis: auto + } + + .navbar-expand-xxl .navbar-toggler { + display: none + } +} + +.navbar-expand { + flex-wrap: nowrap; + justify-content: flex-start +} + +.navbar-expand .navbar-nav { + flex-direction: row +} + +.navbar-expand .navbar-nav .dropdown-menu { + position: absolute +} + +.navbar-expand .navbar-nav .nav-link { + padding-right: .5rem; + padding-left: .5rem +} + +.navbar-expand .navbar-nav-scroll { + overflow: visible +} + +.navbar-expand .navbar-collapse { + display: flex !important; + flex-basis: auto +} + +.navbar-expand .navbar-toggler { + display: none +} + +.navbar-light .navbar-brand { + color: rgba(0, 0, 0, .9) +} + +.navbar-light .navbar-brand:focus, .navbar-light .navbar-brand:hover { + color: rgba(0, 0, 0, .9) +} + +.navbar-light .navbar-nav .nav-link { + color: rgba(0, 0, 0, .55) +} + +.navbar-light .navbar-nav .nav-link:focus, .navbar-light .navbar-nav .nav-link:hover { + color: rgba(0, 0, 0, .7) +} + +.navbar-light .navbar-nav .nav-link.disabled { + color: rgba(0, 0, 0, .3) +} + +.navbar-light .navbar-nav .nav-link.active, .navbar-light .navbar-nav .show > .nav-link { + color: rgba(0, 0, 0, .9) +} + +.navbar-light .navbar-toggler { + color: rgba(0, 0, 0, .55); + border-color: rgba(0, 0, 0, .1) +} + +.navbar-light .navbar-toggler-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") +} + +.navbar-light .navbar-text { + color: rgba(0, 0, 0, .55) +} + +.navbar-light .navbar-text a, .navbar-light .navbar-text a:focus, .navbar-light .navbar-text a:hover { + color: rgba(0, 0, 0, .9) +} + +.navbar-dark .navbar-brand { + color: #fff +} + +.navbar-dark .navbar-brand:focus, .navbar-dark .navbar-brand:hover { + color: #fff +} + +.navbar-dark .navbar-nav .nav-link { + color: rgba(255, 255, 255, .55) +} + +.navbar-dark .navbar-nav .nav-link:focus, .navbar-dark .navbar-nav .nav-link:hover { + color: rgba(255, 255, 255, .75) +} + +.navbar-dark .navbar-nav .nav-link.disabled { + color: rgba(255, 255, 255, .25) +} + +.navbar-dark .navbar-nav .nav-link.active, .navbar-dark .navbar-nav .show > .nav-link { + color: #fff +} + +.navbar-dark .navbar-toggler { + color: rgba(255, 255, 255, .55); + border-color: rgba(255, 255, 255, .1) +} + +.navbar-dark .navbar-toggler-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") +} + +.navbar-dark .navbar-text { + color: rgba(255, 255, 255, .55) +} + +.navbar-dark .navbar-text a, .navbar-dark .navbar-text a:focus, .navbar-dark .navbar-text a:hover { + color: #fff +} + +.card { + position: relative; + display: flex; + flex-direction: column; + min-width: 0; + word-wrap: break-word; + background-color: #fff; + background-clip: border-box; + border: 1px solid rgba(0, 0, 0, .125); + border-radius: .25rem +} + +.card > hr { + margin-right: 0; + margin-left: 0 +} + +.card > .list-group { + border-top: inherit; + border-bottom: inherit +} + +.card > .list-group:first-child { + border-top-width: 0; + border-top-left-radius: calc(.25rem - 1px); + border-top-right-radius: calc(.25rem - 1px) +} + +.card > .list-group:last-child { + border-bottom-width: 0; + border-bottom-right-radius: calc(.25rem - 1px); + border-bottom-left-radius: calc(.25rem - 1px) +} + +.card > .card-header + .list-group, .card > .list-group + .card-footer { + border-top: 0 +} + +.card-body { + flex: 1 1 auto; + padding: 1rem 1rem +} + +.card-title { + margin-bottom: .5rem +} + +.card-subtitle { + margin-top: -.25rem; + margin-bottom: 0 +} + +.card-text:last-child { + margin-bottom: 0 +} + +.card-link:hover { + text-decoration: none +} + +.card-link + .card-link { + margin-left: 1rem +} + +.card-header { + padding: .5rem 1rem; + margin-bottom: 0; + background-color: rgba(0, 0, 0, .03); + border-bottom: 1px solid rgba(0, 0, 0, .125) +} + +.card-header:first-child { + border-radius: calc(.25rem - 1px) calc(.25rem - 1px) 0 0 +} + +.card-footer { + padding: .5rem 1rem; + background-color: rgba(0, 0, 0, .03); + border-top: 1px solid rgba(0, 0, 0, .125) +} + +.card-footer:last-child { + border-radius: 0 0 calc(.25rem - 1px) calc(.25rem - 1px) +} + +.card-header-tabs { + margin-right: -.5rem; + margin-bottom: -.5rem; + margin-left: -.5rem; + border-bottom: 0 +} + +.card-header-pills { + margin-right: -.5rem; + margin-left: -.5rem +} + +.card-img-overlay { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + padding: 1rem; + border-radius: calc(.25rem - 1px) +} + +.card-img, .card-img-bottom, .card-img-top { + width: 100% +} + +.card-img, .card-img-top { + border-top-left-radius: calc(.25rem - 1px); + border-top-right-radius: calc(.25rem - 1px) +} + +.card-img, .card-img-bottom { + border-bottom-right-radius: calc(.25rem - 1px); + border-bottom-left-radius: calc(.25rem - 1px) +} + +.card-group > .card { + margin-bottom: .75rem +} + +@media (min-width: 576px) { + .card-group { + display: flex; + flex-flow: row wrap + } + + .card-group > .card { + flex: 1 0 0%; + margin-bottom: 0 + } + + .card-group > .card + .card { + margin-left: 0; + border-left: 0 + } + + .card-group > .card:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0 + } + + .card-group > .card:not(:last-child) .card-header, .card-group > .card:not(:last-child) .card-img-top { + border-top-right-radius: 0 + } + + .card-group > .card:not(:last-child) .card-footer, .card-group > .card:not(:last-child) .card-img-bottom { + border-bottom-right-radius: 0 + } + + .card-group > .card:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0 + } + + .card-group > .card:not(:first-child) .card-header, .card-group > .card:not(:first-child) .card-img-top { + border-top-left-radius: 0 + } + + .card-group > .card:not(:first-child) .card-footer, .card-group > .card:not(:first-child) .card-img-bottom { + border-bottom-left-radius: 0 + } +} + +.accordion-button { + position: relative; + display: flex; + align-items: center; + width: 100%; + padding: 1rem 1.25rem; + font-size: 1rem; + color: #212529; + text-align: left; + background-color: #fff; + border: 0; + border-radius: 0; + overflow-anchor: none; + transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out, border-radius .15s ease +} + +@media (prefers-reduced-motion: reduce) { + .accordion-button { + transition: none + } +} + +.accordion-button:not(.collapsed) { + color: #0c63e4; + background-color: #e7f1ff; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .125) +} + +.accordion-button:not(.collapsed)::after { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%230c63e4'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); + transform: rotate(-180deg) +} + +.accordion-button::after { + flex-shrink: 0; + width: 1.25rem; + height: 1.25rem; + margin-left: auto; + content: ""; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23212529'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-size: 1.25rem; + transition: transform .2s ease-in-out +} + +@media (prefers-reduced-motion: reduce) { + .accordion-button::after { + transition: none + } +} + +.accordion-button:hover { + z-index: 2 +} + +.accordion-button:focus { + z-index: 3; + border-color: #86b7fe; + outline: 0; + box-shadow: 0 0 0 .25rem rgba(13, 110, 253, .25) +} + +.accordion-header { + margin-bottom: 0 +} + +.accordion-item { + background-color: #fff; + border: 1px solid rgba(0, 0, 0, .125) +} + +.accordion-item:first-of-type { + border-top-left-radius: .25rem; + border-top-right-radius: .25rem +} + +.accordion-item:first-of-type .accordion-button { + border-top-left-radius: calc(.25rem - 1px); + border-top-right-radius: calc(.25rem - 1px) +} + +.accordion-item:not(:first-of-type) { + border-top: 0 +} + +.accordion-item:last-of-type { + border-bottom-right-radius: .25rem; + border-bottom-left-radius: .25rem +} + +.accordion-item:last-of-type .accordion-button.collapsed { + border-bottom-right-radius: calc(.25rem - 1px); + border-bottom-left-radius: calc(.25rem - 1px) +} + +.accordion-item:last-of-type .accordion-collapse { + border-bottom-right-radius: .25rem; + border-bottom-left-radius: .25rem +} + +.accordion-body { + padding: 1rem 1.25rem +} + +.accordion-flush .accordion-collapse { + border-width: 0 +} + +.accordion-flush .accordion-item { + border-right: 0; + border-left: 0; + border-radius: 0 +} + +.accordion-flush .accordion-item:first-child { + border-top: 0 +} + +.accordion-flush .accordion-item:last-child { + border-bottom: 0 +} + +.accordion-flush .accordion-item .accordion-button { + border-radius: 0 +} + +.breadcrumb { + display: flex; + flex-wrap: wrap; + padding: 0 0; + margin-bottom: 1rem; + list-style: none +} + +.breadcrumb-item + .breadcrumb-item { + padding-left: .5rem +} + +.breadcrumb-item + .breadcrumb-item::before { + float: left; + padding-right: .5rem; + color: #6c757d; + content: var(--bs-breadcrumb-divider, "/") +} + +.breadcrumb-item.active { + color: #6c757d +} + +.pagination { + display: flex; + padding-left: 0; + list-style: none +} + +.page-link { + position: relative; + display: block; + color: #0d6efd; + text-decoration: none; + background-color: #fff; + border: 1px solid #dee2e6; + transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out +} + +@media (prefers-reduced-motion: reduce) { + .page-link { + transition: none + } +} + +.page-link:hover { + z-index: 2; + color: #0a58ca; + background-color: #e9ecef; + border-color: #dee2e6 +} + +.page-link:focus { + z-index: 3; + color: #0a58ca; + background-color: #e9ecef; + outline: 0; + box-shadow: 0 0 0 .25rem rgba(13, 110, 253, .25) +} + +.page-item:not(:first-child) .page-link { + margin-left: -1px +} + +.page-item.active .page-link { + z-index: 3; + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd +} + +.page-item.disabled .page-link { + color: #6c757d; + pointer-events: none; + background-color: #fff; + border-color: #dee2e6 +} + +.page-link { + padding: .375rem .75rem +} + +.page-item:first-child .page-link { + border-top-left-radius: .25rem; + border-bottom-left-radius: .25rem +} + +.page-item:last-child .page-link { + border-top-right-radius: .25rem; + border-bottom-right-radius: .25rem +} + +.pagination-lg .page-link { + padding: .75rem 1.5rem; + font-size: 1.25rem +} + +.pagination-lg .page-item:first-child .page-link { + border-top-left-radius: .3rem; + border-bottom-left-radius: .3rem +} + +.pagination-lg .page-item:last-child .page-link { + border-top-right-radius: .3rem; + border-bottom-right-radius: .3rem +} + +.pagination-sm .page-link { + padding: .25rem .5rem; + font-size: .875rem +} + +.pagination-sm .page-item:first-child .page-link { + border-top-left-radius: .2rem; + border-bottom-left-radius: .2rem +} + +.pagination-sm .page-item:last-child .page-link { + border-top-right-radius: .2rem; + border-bottom-right-radius: .2rem +} + +.badge { + display: inline-block; + padding: .35em .65em; + font-size: .75em; + font-weight: 700; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25rem +} + +.badge:empty { + display: none +} + +.btn .badge { + position: relative; + top: -1px +} + +.alert { + position: relative; + padding: 1rem 1rem; + margin-bottom: 1rem; + border: 1px solid transparent; + border-radius: .25rem +} + +.alert-heading { + color: inherit +} + +.alert-link { + font-weight: 700 +} + +.alert-dismissible { + padding-right: 3rem +} + +.alert-dismissible .btn-close { + position: absolute; + top: 0; + right: 0; + z-index: 2; + padding: 1.25rem 1rem +} + +.alert-primary { + color: #084298; + background-color: #cfe2ff; + border-color: #b6d4fe +} + +.alert-primary .alert-link { + color: #06357a +} + +.alert-secondary { + color: #41464b; + background-color: #e2e3e5; + border-color: #d3d6d8 +} + +.alert-secondary .alert-link { + color: #34383c +} + +.alert-success { + color: #0f5132; + background-color: #d1e7dd; + border-color: #badbcc +} + +.alert-success .alert-link { + color: #0c4128 +} + +.alert-info { + color: #055160; + background-color: #cff4fc; + border-color: #b6effb +} + +.alert-info .alert-link { + color: #04414d +} + +.alert-warning { + color: #664d03; + background-color: #fff3cd; + border-color: #ffecb5 +} + +.alert-warning .alert-link { + color: #523e02 +} + +.alert-danger { + color: #842029; + background-color: #f8d7da; + border-color: #f5c2c7 +} + +.alert-danger .alert-link { + color: #6a1a21 +} + +.alert-light { + color: #636464; + background-color: #fefefe; + border-color: #fdfdfe +} + +.alert-light .alert-link { + color: #4f5050 +} + +.alert-dark { + color: #141619; + background-color: #d3d3d4; + border-color: #bcbebf +} + +.alert-dark .alert-link { + color: #101214 +} + +@-webkit-keyframes progress-bar-stripes { + 0% { + background-position-x: 1rem + } +} + +@keyframes progress-bar-stripes { + 0% { + background-position-x: 1rem + } +} + +.progress { + display: flex; + height: 1rem; + overflow: hidden; + font-size: .75rem; + background-color: #e9ecef; + border-radius: .25rem +} + +.progress-bar { + display: flex; + flex-direction: column; + justify-content: center; + overflow: hidden; + color: #fff; + text-align: center; + white-space: nowrap; + background-color: #0d6efd; + transition: width .6s ease +} + +@media (prefers-reduced-motion: reduce) { + .progress-bar { + transition: none + } +} + +.progress-bar-striped { + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-size: 1rem 1rem +} + +.progress-bar-animated { + -webkit-animation: 1s linear infinite progress-bar-stripes; + animation: 1s linear infinite progress-bar-stripes +} + +@media (prefers-reduced-motion: reduce) { + .progress-bar-animated { + -webkit-animation: none; + animation: none + } +} + +.list-group { + display: flex; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; + border-radius: .25rem +} + +.list-group-numbered { + list-style-type: none; + counter-reset: section +} + +.list-group-numbered > li::before { + content: counters(section, ".") ". "; + counter-increment: section +} + +.list-group-item-action { + width: 100%; + color: #495057; + text-align: inherit +} + +.list-group-item-action:focus, .list-group-item-action:hover { + z-index: 1; + color: #495057; + text-decoration: none; + background-color: #f8f9fa +} + +.list-group-item-action:active { + color: #212529; + background-color: #e9ecef +} + +.list-group-item { + position: relative; + display: block; + padding: .5rem 1rem; + color: #212529; + text-decoration: none; + background-color: #fff; + border: 1px solid rgba(0, 0, 0, .125) +} + +.list-group-item:first-child { + border-top-left-radius: inherit; + border-top-right-radius: inherit +} + +.list-group-item:last-child { + border-bottom-right-radius: inherit; + border-bottom-left-radius: inherit +} + +.list-group-item.disabled, .list-group-item:disabled { + color: #6c757d; + pointer-events: none; + background-color: #fff +} + +.list-group-item.active { + z-index: 2; + color: #fff; + background-color: #0d6efd; + border-color: #0d6efd +} + +.list-group-item + .list-group-item { + border-top-width: 0 +} + +.list-group-item + .list-group-item.active { + margin-top: -1px; + border-top-width: 1px +} + +.list-group-horizontal { + flex-direction: row +} + +.list-group-horizontal > .list-group-item:first-child { + border-bottom-left-radius: .25rem; + border-top-right-radius: 0 +} + +.list-group-horizontal > .list-group-item:last-child { + border-top-right-radius: .25rem; + border-bottom-left-radius: 0 +} + +.list-group-horizontal > .list-group-item.active { + margin-top: 0 +} + +.list-group-horizontal > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0 +} + +.list-group-horizontal > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px +} + +@media (min-width: 576px) { + .list-group-horizontal-sm { + flex-direction: row + } + + .list-group-horizontal-sm > .list-group-item:first-child { + border-bottom-left-radius: .25rem; + border-top-right-radius: 0 + } + + .list-group-horizontal-sm > .list-group-item:last-child { + border-top-right-radius: .25rem; + border-bottom-left-radius: 0 + } + + .list-group-horizontal-sm > .list-group-item.active { + margin-top: 0 + } + + .list-group-horizontal-sm > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0 + } + + .list-group-horizontal-sm > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px + } +} + +@media (min-width: 768px) { + .list-group-horizontal-md { + flex-direction: row + } + + .list-group-horizontal-md > .list-group-item:first-child { + border-bottom-left-radius: .25rem; + border-top-right-radius: 0 + } + + .list-group-horizontal-md > .list-group-item:last-child { + border-top-right-radius: .25rem; + border-bottom-left-radius: 0 + } + + .list-group-horizontal-md > .list-group-item.active { + margin-top: 0 + } + + .list-group-horizontal-md > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0 + } + + .list-group-horizontal-md > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px + } +} + +@media (min-width: 992px) { + .list-group-horizontal-lg { + flex-direction: row + } + + .list-group-horizontal-lg > .list-group-item:first-child { + border-bottom-left-radius: .25rem; + border-top-right-radius: 0 + } + + .list-group-horizontal-lg > .list-group-item:last-child { + border-top-right-radius: .25rem; + border-bottom-left-radius: 0 + } + + .list-group-horizontal-lg > .list-group-item.active { + margin-top: 0 + } + + .list-group-horizontal-lg > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0 + } + + .list-group-horizontal-lg > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px + } +} + +@media (min-width: 1200px) { + .list-group-horizontal-xl { + flex-direction: row + } + + .list-group-horizontal-xl > .list-group-item:first-child { + border-bottom-left-radius: .25rem; + border-top-right-radius: 0 + } + + .list-group-horizontal-xl > .list-group-item:last-child { + border-top-right-radius: .25rem; + border-bottom-left-radius: 0 + } + + .list-group-horizontal-xl > .list-group-item.active { + margin-top: 0 + } + + .list-group-horizontal-xl > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0 + } + + .list-group-horizontal-xl > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px + } +} + +@media (min-width: 1400px) { + .list-group-horizontal-xxl { + flex-direction: row + } + + .list-group-horizontal-xxl > .list-group-item:first-child { + border-bottom-left-radius: .25rem; + border-top-right-radius: 0 + } + + .list-group-horizontal-xxl > .list-group-item:last-child { + border-top-right-radius: .25rem; + border-bottom-left-radius: 0 + } + + .list-group-horizontal-xxl > .list-group-item.active { + margin-top: 0 + } + + .list-group-horizontal-xxl > .list-group-item + .list-group-item { + border-top-width: 1px; + border-left-width: 0 + } + + .list-group-horizontal-xxl > .list-group-item + .list-group-item.active { + margin-left: -1px; + border-left-width: 1px + } +} + +.list-group-flush { + border-radius: 0 +} + +.list-group-flush > .list-group-item { + border-width: 0 0 1px +} + +.list-group-flush > .list-group-item:last-child { + border-bottom-width: 0 +} + +.list-group-item-primary { + color: #084298; + background-color: #cfe2ff +} + +.list-group-item-primary.list-group-item-action:focus, .list-group-item-primary.list-group-item-action:hover { + color: #084298; + background-color: #bacbe6 +} + +.list-group-item-primary.list-group-item-action.active { + color: #fff; + background-color: #084298; + border-color: #084298 +} + +.list-group-item-secondary { + color: #41464b; + background-color: #e2e3e5 +} + +.list-group-item-secondary.list-group-item-action:focus, .list-group-item-secondary.list-group-item-action:hover { + color: #41464b; + background-color: #cbccce +} + +.list-group-item-secondary.list-group-item-action.active { + color: #fff; + background-color: #41464b; + border-color: #41464b +} + +.list-group-item-success { + color: #0f5132; + background-color: #d1e7dd +} + +.list-group-item-success.list-group-item-action:focus, .list-group-item-success.list-group-item-action:hover { + color: #0f5132; + background-color: #bcd0c7 +} + +.list-group-item-success.list-group-item-action.active { + color: #fff; + background-color: #0f5132; + border-color: #0f5132 +} + +.list-group-item-info { + color: #055160; + background-color: #cff4fc +} + +.list-group-item-info.list-group-item-action:focus, .list-group-item-info.list-group-item-action:hover { + color: #055160; + background-color: #badce3 +} + +.list-group-item-info.list-group-item-action.active { + color: #fff; + background-color: #055160; + border-color: #055160 +} + +.list-group-item-warning { + color: #664d03; + background-color: #fff3cd +} + +.list-group-item-warning.list-group-item-action:focus, .list-group-item-warning.list-group-item-action:hover { + color: #664d03; + background-color: #e6dbb9 +} + +.list-group-item-warning.list-group-item-action.active { + color: #fff; + background-color: #664d03; + border-color: #664d03 +} + +.list-group-item-danger { + color: #842029; + background-color: #f8d7da +} + +.list-group-item-danger.list-group-item-action:focus, .list-group-item-danger.list-group-item-action:hover { + color: #842029; + background-color: #dfc2c4 +} + +.list-group-item-danger.list-group-item-action.active { + color: #fff; + background-color: #842029; + border-color: #842029 +} + +.list-group-item-light { + color: #636464; + background-color: #fefefe +} + +.list-group-item-light.list-group-item-action:focus, .list-group-item-light.list-group-item-action:hover { + color: #636464; + background-color: #e5e5e5 +} + +.list-group-item-light.list-group-item-action.active { + color: #fff; + background-color: #636464; + border-color: #636464 +} + +.list-group-item-dark { + color: #141619; + background-color: #d3d3d4 +} + +.list-group-item-dark.list-group-item-action:focus, .list-group-item-dark.list-group-item-action:hover { + color: #141619; + background-color: #bebebf +} + +.list-group-item-dark.list-group-item-action.active { + color: #fff; + background-color: #141619; + border-color: #141619 +} + +.btn-close { + box-sizing: content-box; + width: 1em; + height: 1em; + padding: .25em .25em; + color: #000; + background: transparent url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 011.414 0L8 6.586 14.293.293a1 1 0 111.414 1.414L9.414 8l6.293 6.293a1 1 0 01-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 01-1.414-1.414L6.586 8 .293 1.707a1 1 0 010-1.414z'/%3e%3c/svg%3e") center/1em auto no-repeat; + border: 0; + border-radius: .25rem; + opacity: .5 +} + +.btn-close:hover { + color: #000; + text-decoration: none; + opacity: .75 +} + +.btn-close:focus { + outline: 0; + box-shadow: 0 0 0 .25rem rgba(13, 110, 253, .25); + opacity: 1 +} + +.btn-close.disabled, .btn-close:disabled { + pointer-events: none; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + opacity: .25 +} + +.btn-close-white { + filter: invert(1) grayscale(100%) brightness(200%) +} + +.toast { + width: 350px; + max-width: 100%; + font-size: .875rem; + pointer-events: auto; + background-color: rgba(255, 255, 255, .85); + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, .1); + box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .15); + border-radius: .25rem +} + +.toast:not(.showing):not(.show) { + opacity: 0 +} + +.toast.hide { + display: none +} + +.toast-container { + width: -webkit-max-content; + width: -moz-max-content; + width: max-content; + max-width: 100%; + pointer-events: none +} + +.toast-container > :not(:last-child) { + margin-bottom: .75rem +} + +.toast-header { + display: flex; + align-items: center; + padding: .5rem .75rem; + color: #6c757d; + background-color: rgba(255, 255, 255, .85); + background-clip: padding-box; + border-bottom: 1px solid rgba(0, 0, 0, .05); + border-top-left-radius: calc(.25rem - 1px); + border-top-right-radius: calc(.25rem - 1px) +} + +.toast-header .btn-close { + margin-right: -.375rem; + margin-left: .75rem +} + +.toast-body { + padding: .75rem; + word-wrap: break-word +} + +.modal { + position: fixed; + top: 0; + left: 0; + z-index: 1060; + display: none; + width: 100%; + height: 100%; + overflow-x: hidden; + overflow-y: auto; + outline: 0 +} + +.modal-dialog { + position: relative; + width: auto; + margin: .5rem; + pointer-events: none +} + +.modal.fade .modal-dialog { + transition: transform .3s ease-out; + transform: translate(0, -50px) +} + +@media (prefers-reduced-motion: reduce) { + .modal.fade .modal-dialog { + transition: none + } +} + +.modal.show .modal-dialog { + transform: none +} + +.modal.modal-static .modal-dialog { + transform: scale(1.02) +} + +.modal-dialog-scrollable { + height: calc(100% - 1rem) +} + +.modal-dialog-scrollable .modal-content { + max-height: 100%; + overflow: hidden +} + +.modal-dialog-scrollable .modal-body { + overflow-y: auto +} + +.modal-dialog-centered { + display: flex; + align-items: center; + min-height: calc(100% - 1rem) +} + +.modal-content { + position: relative; + display: flex; + flex-direction: column; + width: 100%; + pointer-events: auto; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: .3rem; + outline: 0 +} + +.modal-backdrop { + position: fixed; + top: 0; + left: 0; + z-index: 1040; + width: 100vw; + height: 100vh; + background-color: #000 +} + +.modal-backdrop.fade { + opacity: 0 +} + +.modal-backdrop.show { + opacity: .5 +} + +.modal-header { + display: flex; + flex-shrink: 0; + align-items: center; + justify-content: space-between; + padding: 1rem 1rem; + border-bottom: 1px solid #dee2e6; + border-top-left-radius: calc(.3rem - 1px); + border-top-right-radius: calc(.3rem - 1px) +} + +.modal-header .btn-close { + padding: .5rem .5rem; + margin: -.5rem -.5rem -.5rem auto +} + +.modal-title { + margin-bottom: 0; + line-height: 1.5 +} + +.modal-body { + position: relative; + flex: 1 1 auto; + padding: 1rem +} + +.modal-footer { + display: flex; + flex-wrap: wrap; + flex-shrink: 0; + align-items: center; + justify-content: flex-end; + padding: .75rem; + border-top: 1px solid #dee2e6; + border-bottom-right-radius: calc(.3rem - 1px); + border-bottom-left-radius: calc(.3rem - 1px) +} + +.modal-footer > * { + margin: .25rem +} + +@media (min-width: 576px) { + .modal-dialog { + max-width: 500px; + margin: 1.75rem auto + } + + .modal-dialog-scrollable { + height: calc(100% - 3.5rem) + } + + .modal-dialog-centered { + min-height: calc(100% - 3.5rem) + } + + .modal-sm { + max-width: 300px + } +} + +@media (min-width: 992px) { + .modal-lg, .modal-xl { + max-width: 800px + } +} + +@media (min-width: 1200px) { + .modal-xl { + max-width: 1140px + } +} + +.modal-fullscreen { + width: 100vw; + max-width: none; + height: 100%; + margin: 0 +} + +.modal-fullscreen .modal-content { + height: 100%; + border: 0; + border-radius: 0 +} + +.modal-fullscreen .modal-header { + border-radius: 0 +} + +.modal-fullscreen .modal-body { + overflow-y: auto +} + +.modal-fullscreen .modal-footer { + border-radius: 0 +} + +@media (max-width: 575.98px) { + .modal-fullscreen-sm-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0 + } + + .modal-fullscreen-sm-down .modal-content { + height: 100%; + border: 0; + border-radius: 0 + } + + .modal-fullscreen-sm-down .modal-header { + border-radius: 0 + } + + .modal-fullscreen-sm-down .modal-body { + overflow-y: auto + } + + .modal-fullscreen-sm-down .modal-footer { + border-radius: 0 + } +} + +@media (max-width: 767.98px) { + .modal-fullscreen-md-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0 + } + + .modal-fullscreen-md-down .modal-content { + height: 100%; + border: 0; + border-radius: 0 + } + + .modal-fullscreen-md-down .modal-header { + border-radius: 0 + } + + .modal-fullscreen-md-down .modal-body { + overflow-y: auto + } + + .modal-fullscreen-md-down .modal-footer { + border-radius: 0 + } +} + +@media (max-width: 991.98px) { + .modal-fullscreen-lg-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0 + } + + .modal-fullscreen-lg-down .modal-content { + height: 100%; + border: 0; + border-radius: 0 + } + + .modal-fullscreen-lg-down .modal-header { + border-radius: 0 + } + + .modal-fullscreen-lg-down .modal-body { + overflow-y: auto + } + + .modal-fullscreen-lg-down .modal-footer { + border-radius: 0 + } +} + +@media (max-width: 1199.98px) { + .modal-fullscreen-xl-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0 + } + + .modal-fullscreen-xl-down .modal-content { + height: 100%; + border: 0; + border-radius: 0 + } + + .modal-fullscreen-xl-down .modal-header { + border-radius: 0 + } + + .modal-fullscreen-xl-down .modal-body { + overflow-y: auto + } + + .modal-fullscreen-xl-down .modal-footer { + border-radius: 0 + } +} + +@media (max-width: 1399.98px) { + .modal-fullscreen-xxl-down { + width: 100vw; + max-width: none; + height: 100%; + margin: 0 + } + + .modal-fullscreen-xxl-down .modal-content { + height: 100%; + border: 0; + border-radius: 0 + } + + .modal-fullscreen-xxl-down .modal-header { + border-radius: 0 + } + + .modal-fullscreen-xxl-down .modal-body { + overflow-y: auto + } + + .modal-fullscreen-xxl-down .modal-footer { + border-radius: 0 + } +} + +.tooltip { + position: absolute; + z-index: 1080; + display: block; + margin: 0; + font-family: var(--bs-font-sans-serif); + font-style: normal; + font-weight: 400; + line-height: 1.5; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + white-space: normal; + line-break: auto; + font-size: .875rem; + word-wrap: break-word; + opacity: 0 +} + +.tooltip.show { + opacity: .9 +} + +.tooltip .tooltip-arrow { + position: absolute; + display: block; + width: .8rem; + height: .4rem +} + +.tooltip .tooltip-arrow::before { + position: absolute; + content: ""; + border-color: transparent; + border-style: solid +} + +.bs-tooltip-auto[data-popper-placement^=top], .bs-tooltip-top { + padding: .4rem 0 +} + +.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow, .bs-tooltip-top .tooltip-arrow { + bottom: 0 +} + +.bs-tooltip-auto[data-popper-placement^=top] .tooltip-arrow::before, .bs-tooltip-top .tooltip-arrow::before { + top: -1px; + border-width: .4rem .4rem 0; + border-top-color: #000 +} + +.bs-tooltip-auto[data-popper-placement^=right], .bs-tooltip-end { + padding: 0 .4rem +} + +.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow, .bs-tooltip-end .tooltip-arrow { + left: 0; + width: .4rem; + height: .8rem +} + +.bs-tooltip-auto[data-popper-placement^=right] .tooltip-arrow::before, .bs-tooltip-end .tooltip-arrow::before { + right: -1px; + border-width: .4rem .4rem .4rem 0; + border-right-color: #000 +} + +.bs-tooltip-auto[data-popper-placement^=bottom], .bs-tooltip-bottom { + padding: .4rem 0 +} + +.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow, .bs-tooltip-bottom .tooltip-arrow { + top: 0 +} + +.bs-tooltip-auto[data-popper-placement^=bottom] .tooltip-arrow::before, .bs-tooltip-bottom .tooltip-arrow::before { + bottom: -1px; + border-width: 0 .4rem .4rem; + border-bottom-color: #000 +} + +.bs-tooltip-auto[data-popper-placement^=left], .bs-tooltip-start { + padding: 0 .4rem +} + +.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow, .bs-tooltip-start .tooltip-arrow { + right: 0; + width: .4rem; + height: .8rem +} + +.bs-tooltip-auto[data-popper-placement^=left] .tooltip-arrow::before, .bs-tooltip-start .tooltip-arrow::before { + left: -1px; + border-width: .4rem 0 .4rem .4rem; + border-left-color: #000 +} + +.tooltip-inner { + max-width: 200px; + padding: .25rem .5rem; + color: #fff; + text-align: center; + background-color: #000; + border-radius: .25rem +} + +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1070; + display: block; + max-width: 276px; + font-family: var(--bs-font-sans-serif); + font-style: normal; + font-weight: 400; + line-height: 1.5; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + white-space: normal; + line-break: auto; + font-size: .875rem; + word-wrap: break-word; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: .3rem +} + +.popover .popover-arrow { + position: absolute; + display: block; + width: 1rem; + height: .5rem +} + +.popover .popover-arrow::after, .popover .popover-arrow::before { + position: absolute; + display: block; + content: ""; + border-color: transparent; + border-style: solid +} + +.bs-popover-auto[data-popper-placement^=top] > .popover-arrow, .bs-popover-top > .popover-arrow { + bottom: calc(-.5rem - 1px) +} + +.bs-popover-auto[data-popper-placement^=top] > .popover-arrow::before, .bs-popover-top > .popover-arrow::before { + bottom: 0; + border-width: .5rem .5rem 0; + border-top-color: rgba(0, 0, 0, .25) +} + +.bs-popover-auto[data-popper-placement^=top] > .popover-arrow::after, .bs-popover-top > .popover-arrow::after { + bottom: 1px; + border-width: .5rem .5rem 0; + border-top-color: #fff +} + +.bs-popover-auto[data-popper-placement^=right] > .popover-arrow, .bs-popover-end > .popover-arrow { + left: calc(-.5rem - 1px); + width: .5rem; + height: 1rem +} + +.bs-popover-auto[data-popper-placement^=right] > .popover-arrow::before, .bs-popover-end > .popover-arrow::before { + left: 0; + border-width: .5rem .5rem .5rem 0; + border-right-color: rgba(0, 0, 0, .25) +} + +.bs-popover-auto[data-popper-placement^=right] > .popover-arrow::after, .bs-popover-end > .popover-arrow::after { + left: 1px; + border-width: .5rem .5rem .5rem 0; + border-right-color: #fff +} + +.bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow, .bs-popover-bottom > .popover-arrow { + top: calc(-.5rem - 1px) +} + +.bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::before, .bs-popover-bottom > .popover-arrow::before { + top: 0; + border-width: 0 .5rem .5rem .5rem; + border-bottom-color: rgba(0, 0, 0, .25) +} + +.bs-popover-auto[data-popper-placement^=bottom] > .popover-arrow::after, .bs-popover-bottom > .popover-arrow::after { + top: 1px; + border-width: 0 .5rem .5rem .5rem; + border-bottom-color: #fff +} + +.bs-popover-auto[data-popper-placement^=bottom] .popover-header::before, .bs-popover-bottom .popover-header::before { + position: absolute; + top: 0; + left: 50%; + display: block; + width: 1rem; + margin-left: -.5rem; + content: ""; + border-bottom: 1px solid #f0f0f0 +} + +.bs-popover-auto[data-popper-placement^=left] > .popover-arrow, .bs-popover-start > .popover-arrow { + right: calc(-.5rem - 1px); + width: .5rem; + height: 1rem +} + +.bs-popover-auto[data-popper-placement^=left] > .popover-arrow::before, .bs-popover-start > .popover-arrow::before { + right: 0; + border-width: .5rem 0 .5rem .5rem; + border-left-color: rgba(0, 0, 0, .25) +} + +.bs-popover-auto[data-popper-placement^=left] > .popover-arrow::after, .bs-popover-start > .popover-arrow::after { + right: 1px; + border-width: .5rem 0 .5rem .5rem; + border-left-color: #fff +} + +.popover-header { + padding: .5rem 1rem; + margin-bottom: 0; + font-size: 1rem; + background-color: #f0f0f0; + border-bottom: 1px solid rgba(0, 0, 0, .2); + border-top-left-radius: calc(.3rem - 1px); + border-top-right-radius: calc(.3rem - 1px) +} + +.popover-header:empty { + display: none +} + +.popover-body { + padding: 1rem 1rem; + color: #212529 +} + +.carousel { + position: relative +} + +.carousel.pointer-event { + touch-action: pan-y +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden +} + +.carousel-inner::after { + display: block; + clear: both; + content: "" +} + +.carousel-item { + position: relative; + display: none; + float: left; + width: 100%; + margin-right: -100%; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + transition: transform .6s ease-in-out +} + +@media (prefers-reduced-motion: reduce) { + .carousel-item { + transition: none + } +} + +.carousel-item-next, .carousel-item-prev, .carousel-item.active { + display: block +} + +.active.carousel-item-end, .carousel-item-next:not(.carousel-item-start) { + transform: translateX(100%) +} + +.active.carousel-item-start, .carousel-item-prev:not(.carousel-item-end) { + transform: translateX(-100%) +} + +.carousel-fade .carousel-item { + opacity: 0; + transition-property: opacity; + transform: none +} + +.carousel-fade .carousel-item-next.carousel-item-start, .carousel-fade .carousel-item-prev.carousel-item-end, .carousel-fade .carousel-item.active { + z-index: 1; + opacity: 1 +} + +.carousel-fade .active.carousel-item-end, .carousel-fade .active.carousel-item-start { + z-index: 0; + opacity: 0; + transition: opacity 0s .6s +} + +@media (prefers-reduced-motion: reduce) { + .carousel-fade .active.carousel-item-end, .carousel-fade .active.carousel-item-start { + transition: none + } +} + +.carousel-control-next, .carousel-control-prev { + position: absolute; + top: 0; + bottom: 0; + z-index: 1; + display: flex; + align-items: center; + justify-content: center; + width: 15%; + padding: 0; + color: #fff; + text-align: center; + background: 0 0; + border: 0; + opacity: .5; + transition: opacity .15s ease +} + +@media (prefers-reduced-motion: reduce) { + .carousel-control-next, .carousel-control-prev { + transition: none + } +} + +.carousel-control-next:focus, .carousel-control-next:hover, .carousel-control-prev:focus, .carousel-control-prev:hover { + color: #fff; + text-decoration: none; + outline: 0; + opacity: .9 +} + +.carousel-control-prev { + left: 0 +} + +.carousel-control-next { + right: 0 +} + +.carousel-control-next-icon, .carousel-control-prev-icon { + display: inline-block; + width: 2rem; + height: 2rem; + background-repeat: no-repeat; + background-position: 50%; + background-size: 100% 100% +} + +.carousel-control-prev-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3e%3c/svg%3e") +} + +.carousel-control-next-icon { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23fff'%3e%3cpath d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e") +} + +.carousel-indicators { + position: absolute; + right: 0; + bottom: 0; + left: 0; + z-index: 2; + display: flex; + justify-content: center; + padding: 0; + margin-right: 15%; + margin-bottom: 1rem; + margin-left: 15%; + list-style: none +} + +.carousel-indicators [data-bs-target] { + box-sizing: content-box; + flex: 0 1 auto; + width: 30px; + height: 3px; + padding: 0; + margin-right: 3px; + margin-left: 3px; + text-indent: -999px; + cursor: pointer; + background-color: #fff; + background-clip: padding-box; + border: 0; + border-top: 10px solid transparent; + border-bottom: 10px solid transparent; + opacity: .5; + transition: opacity .6s ease +} + +@media (prefers-reduced-motion: reduce) { + .carousel-indicators [data-bs-target] { + transition: none + } +} + +.carousel-indicators .active { + opacity: 1 +} + +.carousel-caption { + position: absolute; + right: 15%; + bottom: 1.25rem; + left: 15%; + padding-top: 1.25rem; + padding-bottom: 1.25rem; + color: #fff; + text-align: center +} + +.carousel-dark .carousel-control-next-icon, .carousel-dark .carousel-control-prev-icon { + filter: invert(1) grayscale(100) +} + +.carousel-dark .carousel-indicators [data-bs-target] { + background-color: #000 +} + +.carousel-dark .carousel-caption { + color: #000 +} + +@-webkit-keyframes spinner-border { + to { + transform: rotate(360deg) + } +} + +@keyframes spinner-border { + to { + transform: rotate(360deg) + } +} + +.spinner-border { + display: inline-block; + width: 2rem; + height: 2rem; + vertical-align: -.125em; + border: .25em solid currentColor; + border-right-color: transparent; + border-radius: 50%; + -webkit-animation: .75s linear infinite spinner-border; + animation: .75s linear infinite spinner-border +} + +.spinner-border-sm { + width: 1rem; + height: 1rem; + border-width: .2em +} + +@-webkit-keyframes spinner-grow { + 0% { + transform: scale(0) + } + 50% { + opacity: 1; + transform: none + } +} + +@keyframes spinner-grow { + 0% { + transform: scale(0) + } + 50% { + opacity: 1; + transform: none + } +} + +.spinner-grow { + display: inline-block; + width: 2rem; + height: 2rem; + vertical-align: -.125em; + background-color: currentColor; + border-radius: 50%; + opacity: 0; + -webkit-animation: .75s linear infinite spinner-grow; + animation: .75s linear infinite spinner-grow +} + +.spinner-grow-sm { + width: 1rem; + height: 1rem +} + +@media (prefers-reduced-motion: reduce) { + .spinner-border, .spinner-grow { + -webkit-animation-duration: 1.5s; + animation-duration: 1.5s + } +} + +.offcanvas { + position: fixed; + bottom: 0; + z-index: 1050; + display: flex; + flex-direction: column; + max-width: 100%; + visibility: hidden; + background-color: #fff; + background-clip: padding-box; + outline: 0; + transition: transform .3s ease-in-out +} + +@media (prefers-reduced-motion: reduce) { + .offcanvas { + transition: none + } +} + +.offcanvas-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1rem 1rem +} + +.offcanvas-header .btn-close { + padding: .5rem .5rem; + margin-top: -.5rem; + margin-right: -.5rem; + margin-bottom: -.5rem +} + +.offcanvas-title { + margin-bottom: 0; + line-height: 1.5 +} + +.offcanvas-body { + flex-grow: 1; + padding: 1rem 1rem; + overflow-y: auto +} + +.offcanvas-start { + top: 0; + left: 0; + width: 400px; + border-right: 1px solid rgba(0, 0, 0, .2); + transform: translateX(-100%) +} + +.offcanvas-end { + top: 0; + right: 0; + width: 400px; + border-left: 1px solid rgba(0, 0, 0, .2); + transform: translateX(100%) +} + +.offcanvas-top { + top: 0; + right: 0; + left: 0; + height: 30vh; + max-height: 100%; + border-bottom: 1px solid rgba(0, 0, 0, .2); + transform: translateY(-100%) +} + +.offcanvas-bottom { + right: 0; + left: 0; + height: 30vh; + max-height: 100%; + border-top: 1px solid rgba(0, 0, 0, .2); + transform: translateY(100%) +} + +.offcanvas.show { + transform: none +} + +.clearfix::after { + display: block; + clear: both; + content: "" +} + +.link-primary { + color: #0d6efd +} + +.link-primary:focus, .link-primary:hover { + color: #0a58ca +} + +.link-secondary { + color: #6c757d +} + +.link-secondary:focus, .link-secondary:hover { + color: #565e64 +} + +.link-success { + color: #198754 +} + +.link-success:focus, .link-success:hover { + color: #146c43 +} + +.link-info { + color: #0dcaf0 +} + +.link-info:focus, .link-info:hover { + color: #3dd5f3 +} + +.link-warning { + color: #ffc107 +} + +.link-warning:focus, .link-warning:hover { + color: #ffcd39 +} + +.link-danger { + color: #dc3545 +} + +.link-danger:focus, .link-danger:hover { + color: #b02a37 +} + +.link-light { + color: #f8f9fa +} + +.link-light:focus, .link-light:hover { + color: #f9fafb +} + +.link-dark { + color: #212529 +} + +.link-dark:focus, .link-dark:hover { + color: #1a1e21 +} + +.ratio { + position: relative; + width: 100% +} + +.ratio::before { + display: block; + padding-top: var(--bs-aspect-ratio); + content: "" +} + +.ratio > * { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100% +} + +.ratio-1x1 { + --bs-aspect-ratio: 100% +} + +.ratio-4x3 { + --bs-aspect-ratio: calc(3 / 4 * 100%) +} + +.ratio-16x9 { + --bs-aspect-ratio: calc(9 / 16 * 100%) +} + +.ratio-21x9 { + --bs-aspect-ratio: calc(9 / 21 * 100%) +} + +.fixed-top { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 1030 +} + +.fixed-bottom { + position: fixed; + right: 0; + bottom: 0; + left: 0; + z-index: 1030 +} + +.sticky-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020 +} + +@media (min-width: 576px) { + .sticky-sm-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020 + } +} + +@media (min-width: 768px) { + .sticky-md-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020 + } +} + +@media (min-width: 992px) { + .sticky-lg-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020 + } +} + +@media (min-width: 1200px) { + .sticky-xl-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020 + } +} + +@media (min-width: 1400px) { + .sticky-xxl-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020 + } +} + +.visually-hidden, .visually-hidden-focusable:not(:focus):not(:focus-within) { + position: absolute !important; + width: 1px !important; + height: 1px !important; + padding: 0 !important; + margin: -1px !important; + overflow: hidden !important; + clip: rect(0, 0, 0, 0) !important; + white-space: nowrap !important; + border: 0 !important +} + +.stretched-link::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1; + content: "" +} + +.text-truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap +} + +.align-baseline { + vertical-align: baseline !important +} + +.align-top { + vertical-align: top !important +} + +.align-middle { + vertical-align: middle !important +} + +.align-bottom { + vertical-align: bottom !important +} + +.align-text-bottom { + vertical-align: text-bottom !important +} + +.align-text-top { + vertical-align: text-top !important +} + +.float-start { + float: left !important +} + +.float-end { + float: right !important +} + +.float-none { + float: none !important +} + +.overflow-auto { + overflow: auto !important +} + +.overflow-hidden { + overflow: hidden !important +} + +.overflow-visible { + overflow: visible !important +} + +.overflow-scroll { + overflow: scroll !important +} + +.d-inline { + display: inline !important +} + +.d-inline-block { + display: inline-block !important +} + +.d-block { + display: block !important +} + +.d-grid { + display: grid !important +} + +.d-table { + display: table !important +} + +.d-table-row { + display: table-row !important +} + +.d-table-cell { + display: table-cell !important +} + +.d-flex { + display: flex !important +} + +.d-inline-flex { + display: inline-flex !important +} + +.d-none { + display: none !important +} + +.shadow { + box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .15) !important +} + +.shadow-sm { + box-shadow: 0 .125rem .25rem rgba(0, 0, 0, .075) !important +} + +.shadow-lg { + box-shadow: 0 1rem 3rem rgba(0, 0, 0, .175) !important +} + +.shadow-none { + box-shadow: none !important +} + +.position-static { + position: static !important +} + +.position-relative { + position: relative !important +} + +.position-absolute { + position: absolute !important +} + +.position-fixed { + position: fixed !important +} + +.position-sticky { + position: -webkit-sticky !important; + position: sticky !important +} + +.top-0 { + top: 0 !important +} + +.top-50 { + top: 50% !important +} + +.top-100 { + top: 100% !important +} + +.bottom-0 { + bottom: 0 !important +} + +.bottom-50 { + bottom: 50% !important +} + +.bottom-100 { + bottom: 100% !important +} + +.start-0 { + left: 0 !important +} + +.start-50 { + left: 50% !important +} + +.start-100 { + left: 100% !important +} + +.end-0 { + right: 0 !important +} + +.end-50 { + right: 50% !important +} + +.end-100 { + right: 100% !important +} + +.translate-middle { + transform: translate(-50%, -50%) !important +} + +.translate-middle-x { + transform: translateX(-50%) !important +} + +.translate-middle-y { + transform: translateY(-50%) !important +} + +.border { + border: 1px solid #dee2e6 !important +} + +.border-0 { + border: 0 !important +} + +.border-top { + border-top: 1px solid #dee2e6 !important +} + +.border-top-0 { + border-top: 0 !important +} + +.border-end { + border-right: 1px solid #dee2e6 !important +} + +.border-end-0 { + border-right: 0 !important +} + +.border-bottom { + border-bottom: 1px solid #dee2e6 !important +} + +.border-bottom-0 { + border-bottom: 0 !important +} + +.border-start { + border-left: 1px solid #dee2e6 !important +} + +.border-start-0 { + border-left: 0 !important +} + +.border-primary { + border-color: #0d6efd !important +} + +.border-secondary { + border-color: #6c757d !important +} + +.border-success { + border-color: #198754 !important +} + +.border-info { + border-color: #0dcaf0 !important +} + +.border-warning { + border-color: #ffc107 !important +} + +.border-danger { + border-color: #dc3545 !important +} + +.border-light { + border-color: #f8f9fa !important +} + +.border-dark { + border-color: #212529 !important +} + +.border-white { + border-color: #fff !important +} + +.border-1 { + border-width: 1px !important +} + +.border-2 { + border-width: 2px !important +} + +.border-3 { + border-width: 3px !important +} + +.border-4 { + border-width: 4px !important +} + +.border-5 { + border-width: 5px !important +} + +.w-25 { + width: 25% !important +} + +.w-50 { + width: 50% !important +} + +.w-75 { + width: 75% !important +} + +.w-100 { + width: 100% !important +} + +.w-auto { + width: auto !important +} + +.mw-100 { + max-width: 100% !important +} + +.vw-100 { + width: 100vw !important +} + +.min-vw-100 { + min-width: 100vw !important +} + +.h-25 { + height: 25% !important +} + +.h-50 { + height: 50% !important +} + +.h-75 { + height: 75% !important +} + +.h-100 { + height: 100% !important +} + +.h-auto { + height: auto !important +} + +.mh-100 { + max-height: 100% !important +} + +.vh-100 { + height: 100vh !important +} + +.min-vh-100 { + min-height: 100vh !important +} + +.flex-fill { + flex: 1 1 auto !important +} + +.flex-row { + flex-direction: row !important +} + +.flex-column { + flex-direction: column !important +} + +.flex-row-reverse { + flex-direction: row-reverse !important +} + +.flex-column-reverse { + flex-direction: column-reverse !important +} + +.flex-grow-0 { + flex-grow: 0 !important +} + +.flex-grow-1 { + flex-grow: 1 !important +} + +.flex-shrink-0 { + flex-shrink: 0 !important +} + +.flex-shrink-1 { + flex-shrink: 1 !important +} + +.flex-wrap { + flex-wrap: wrap !important +} + +.flex-nowrap { + flex-wrap: nowrap !important +} + +.flex-wrap-reverse { + flex-wrap: wrap-reverse !important +} + +.gap-0 { + gap: 0 !important +} + +.gap-1 { + gap: .25rem !important +} + +.gap-2 { + gap: .5rem !important +} + +.gap-3 { + gap: 1rem !important +} + +.gap-4 { + gap: 1.5rem !important +} + +.gap-5 { + gap: 3rem !important +} + +.justify-content-start { + justify-content: flex-start !important +} + +.justify-content-end { + justify-content: flex-end !important +} + +.justify-content-center { + justify-content: center !important +} + +.justify-content-between { + justify-content: space-between !important +} + +.justify-content-around { + justify-content: space-around !important +} + +.justify-content-evenly { + justify-content: space-evenly !important +} + +.align-items-start { + align-items: flex-start !important +} + +.align-items-end { + align-items: flex-end !important +} + +.align-items-center { + align-items: center !important +} + +.align-items-baseline { + align-items: baseline !important +} + +.align-items-stretch { + align-items: stretch !important +} + +.align-content-start { + align-content: flex-start !important +} + +.align-content-end { + align-content: flex-end !important +} + +.align-content-center { + align-content: center !important +} + +.align-content-between { + align-content: space-between !important +} + +.align-content-around { + align-content: space-around !important +} + +.align-content-stretch { + align-content: stretch !important +} + +.align-self-auto { + align-self: auto !important +} + +.align-self-start { + align-self: flex-start !important +} + +.align-self-end { + align-self: flex-end !important +} + +.align-self-center { + align-self: center !important +} + +.align-self-baseline { + align-self: baseline !important +} + +.align-self-stretch { + align-self: stretch !important +} + +.order-first { + order: -1 !important +} + +.order-0 { + order: 0 !important +} + +.order-1 { + order: 1 !important +} + +.order-2 { + order: 2 !important +} + +.order-3 { + order: 3 !important +} + +.order-4 { + order: 4 !important +} + +.order-5 { + order: 5 !important +} + +.order-last { + order: 6 !important +} + +.m-0 { + margin: 0 !important +} + +.m-1 { + margin: .25rem !important +} + +.m-2 { + margin: .5rem !important +} + +.m-3 { + margin: 1rem !important +} + +.m-4 { + margin: 1.5rem !important +} + +.m-5 { + margin: 3rem !important +} + +.m-auto { + margin: auto !important +} + +.mx-0 { + margin-right: 0 !important; + margin-left: 0 !important +} + +.mx-1 { + margin-right: .25rem !important; + margin-left: .25rem !important +} + +.mx-2 { + margin-right: .5rem !important; + margin-left: .5rem !important +} + +.mx-3 { + margin-right: 1rem !important; + margin-left: 1rem !important +} + +.mx-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important +} + +.mx-5 { + margin-right: 3rem !important; + margin-left: 3rem !important +} + +.mx-auto { + margin-right: auto !important; + margin-left: auto !important +} + +.my-0 { + margin-top: 0 !important; + margin-bottom: 0 !important +} + +.my-1 { + margin-top: .25rem !important; + margin-bottom: .25rem !important +} + +.my-2 { + margin-top: .5rem !important; + margin-bottom: .5rem !important +} + +.my-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important +} + +.my-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important +} + +.my-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important +} + +.my-auto { + margin-top: auto !important; + margin-bottom: auto !important +} + +.mt-0 { + margin-top: 0 !important +} + +.mt-1 { + margin-top: .25rem !important +} + +.mt-2 { + margin-top: .5rem !important +} + +.mt-3 { + margin-top: 1rem !important +} + +.mt-4 { + margin-top: 1.5rem !important +} + +.mt-5 { + margin-top: 3rem !important +} + +.mt-auto { + margin-top: auto !important +} + +.me-0 { + margin-right: 0 !important +} + +.me-1 { + margin-right: .25rem !important +} + +.me-2 { + margin-right: .5rem !important +} + +.me-3 { + margin-right: 1rem !important +} + +.me-4 { + margin-right: 1.5rem !important +} + +.me-5 { + margin-right: 3rem !important +} + +.me-auto { + margin-right: auto !important +} + +.mb-0 { + margin-bottom: 0 !important +} + +.mb-1 { + margin-bottom: .25rem !important +} + +.mb-2 { + margin-bottom: .5rem !important +} + +.mb-3 { + margin-bottom: 1rem !important +} + +.mb-4 { + margin-bottom: 1.5rem !important +} + +.mb-5 { + margin-bottom: 3rem !important +} + +.mb-auto { + margin-bottom: auto !important +} + +.ms-0 { + margin-left: 0 !important +} + +.ms-1 { + margin-left: .25rem !important +} + +.ms-2 { + margin-left: .5rem !important +} + +.ms-3 { + margin-left: 1rem !important +} + +.ms-4 { + margin-left: 1.5rem !important +} + +.ms-5 { + margin-left: 3rem !important +} + +.ms-auto { + margin-left: auto !important +} + +.p-0 { + padding: 0 !important +} + +.p-1 { + padding: .25rem !important +} + +.p-2 { + padding: .5rem !important +} + +.p-3 { + padding: 1rem !important +} + +.p-4 { + padding: 1.5rem !important +} + +.p-5 { + padding: 3rem !important +} + +.px-0 { + padding-right: 0 !important; + padding-left: 0 !important +} + +.px-1 { + padding-right: .25rem !important; + padding-left: .25rem !important +} + +.px-2 { + padding-right: .5rem !important; + padding-left: .5rem !important +} + +.px-3 { + padding-right: 1rem !important; + padding-left: 1rem !important +} + +.px-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important +} + +.px-5 { + padding-right: 3rem !important; + padding-left: 3rem !important +} + +.py-0 { + padding-top: 0 !important; + padding-bottom: 0 !important +} + +.py-1 { + padding-top: .25rem !important; + padding-bottom: .25rem !important +} + +.py-2 { + padding-top: .5rem !important; + padding-bottom: .5rem !important +} + +.py-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important +} + +.py-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important +} + +.py-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important +} + +.pt-0 { + padding-top: 0 !important +} + +.pt-1 { + padding-top: .25rem !important +} + +.pt-2 { + padding-top: .5rem !important +} + +.pt-3 { + padding-top: 1rem !important +} + +.pt-4 { + padding-top: 1.5rem !important +} + +.pt-5 { + padding-top: 3rem !important +} + +.pe-0 { + padding-right: 0 !important +} + +.pe-1 { + padding-right: .25rem !important +} + +.pe-2 { + padding-right: .5rem !important +} + +.pe-3 { + padding-right: 1rem !important +} + +.pe-4 { + padding-right: 1.5rem !important +} + +.pe-5 { + padding-right: 3rem !important +} + +.pb-0 { + padding-bottom: 0 !important +} + +.pb-1 { + padding-bottom: .25rem !important +} + +.pb-2 { + padding-bottom: .5rem !important +} + +.pb-3 { + padding-bottom: 1rem !important +} + +.pb-4 { + padding-bottom: 1.5rem !important +} + +.pb-5 { + padding-bottom: 3rem !important +} + +.ps-0 { + padding-left: 0 !important +} + +.ps-1 { + padding-left: .25rem !important +} + +.ps-2 { + padding-left: .5rem !important +} + +.ps-3 { + padding-left: 1rem !important +} + +.ps-4 { + padding-left: 1.5rem !important +} + +.ps-5 { + padding-left: 3rem !important +} + +.font-monospace { + font-family: var(--bs-font-monospace) !important +} + +.fs-1 { + font-size: calc(1.375rem + 1.5vw) !important +} + +.fs-2 { + font-size: calc(1.325rem + .9vw) !important +} + +.fs-3 { + font-size: calc(1.3rem + .6vw) !important +} + +.fs-4 { + font-size: calc(1.275rem + .3vw) !important +} + +.fs-5 { + font-size: 1.25rem !important +} + +.fs-6 { + font-size: 1rem !important +} + +.fst-italic { + font-style: italic !important +} + +.fst-normal { + font-style: normal !important +} + +.fw-light { + font-weight: 300 !important +} + +.fw-lighter { + font-weight: lighter !important +} + +.fw-normal { + font-weight: 400 !important +} + +.fw-bold { + font-weight: 700 !important +} + +.fw-bolder { + font-weight: bolder !important +} + +.lh-1 { + line-height: 1 !important +} + +.lh-sm { + line-height: 1.25 !important +} + +.lh-base { + line-height: 1.5 !important +} + +.lh-lg { + line-height: 2 !important +} + +.text-start { + text-align: left !important +} + +.text-end { + text-align: right !important +} + +.text-center { + text-align: center !important +} + +.text-decoration-none { + text-decoration: none !important +} + +.text-decoration-underline { + text-decoration: underline !important +} + +.text-decoration-line-through { + text-decoration: line-through !important +} + +.text-lowercase { + text-transform: lowercase !important +} + +.text-uppercase { + text-transform: uppercase !important +} + +.text-capitalize { + text-transform: capitalize !important +} + +.text-wrap { + white-space: normal !important +} + +.text-nowrap { + white-space: nowrap !important +} + +.text-break { + word-wrap: break-word !important; + word-break: break-word !important +} + +.text-primary { + color: #0d6efd !important +} + +.text-secondary { + color: #6c757d !important +} + +.text-success { + color: #198754 !important +} + +.text-info { + color: #0dcaf0 !important +} + +.text-warning { + color: #ffc107 !important +} + +.text-danger { + color: #dc3545 !important +} + +.text-light { + color: #f8f9fa !important +} + +.text-dark { + color: #212529 !important +} + +.text-white { + color: #fff !important +} + +.text-body { + color: #212529 !important +} + +.text-muted { + color: #6c757d !important +} + +.text-black-50 { + color: rgba(0, 0, 0, .5) !important +} + +.text-white-50 { + color: rgba(255, 255, 255, .5) !important +} + +.text-reset { + color: inherit !important +} + +.bg-primary { + background-color: #0d6efd !important +} + +.bg-secondary { + background-color: #6c757d !important +} + +.bg-success { + background-color: #198754 !important +} + +.bg-info { + background-color: #0dcaf0 !important +} + +.bg-warning { + background-color: #ffc107 !important +} + +.bg-danger { + background-color: #dc3545 !important +} + +.bg-light { + background-color: #f8f9fa !important +} + +.bg-dark { + background-color: #212529 !important +} + +.bg-body { + background-color: #fff !important +} + +.bg-white { + background-color: #fff !important +} + +.bg-transparent { + background-color: transparent !important +} + +.bg-gradient { + background-image: var(--bs-gradient) !important +} + +.user-select-all { + -webkit-user-select: all !important; + -moz-user-select: all !important; + user-select: all !important +} + +.user-select-auto { + -webkit-user-select: auto !important; + -moz-user-select: auto !important; + user-select: auto !important +} + +.user-select-none { + -webkit-user-select: none !important; + -moz-user-select: none !important; + user-select: none !important +} + +.pe-none { + pointer-events: none !important +} + +.pe-auto { + pointer-events: auto !important +} + +.rounded { + border-radius: .25rem !important +} + +.rounded-0 { + border-radius: 0 !important +} + +.rounded-1 { + border-radius: .2rem !important +} + +.rounded-2 { + border-radius: .25rem !important +} + +.rounded-3 { + border-radius: .3rem !important +} + +.rounded-circle { + border-radius: 50% !important +} + +.rounded-pill { + border-radius: 50rem !important +} + +.rounded-top { + border-top-left-radius: .25rem !important; + border-top-right-radius: .25rem !important +} + +.rounded-end { + border-top-right-radius: .25rem !important; + border-bottom-right-radius: .25rem !important +} + +.rounded-bottom { + border-bottom-right-radius: .25rem !important; + border-bottom-left-radius: .25rem !important +} + +.rounded-start { + border-bottom-left-radius: .25rem !important; + border-top-left-radius: .25rem !important +} + +.visible { + visibility: visible !important +} + +.invisible { + visibility: hidden !important +} + +@media (min-width: 576px) { + .float-sm-start { + float: left !important + } + + .float-sm-end { + float: right !important + } + + .float-sm-none { + float: none !important + } + + .d-sm-inline { + display: inline !important + } + + .d-sm-inline-block { + display: inline-block !important + } + + .d-sm-block { + display: block !important + } + + .d-sm-grid { + display: grid !important + } + + .d-sm-table { + display: table !important + } + + .d-sm-table-row { + display: table-row !important + } + + .d-sm-table-cell { + display: table-cell !important + } + + .d-sm-flex { + display: flex !important + } + + .d-sm-inline-flex { + display: inline-flex !important + } + + .d-sm-none { + display: none !important + } + + .flex-sm-fill { + flex: 1 1 auto !important + } + + .flex-sm-row { + flex-direction: row !important + } + + .flex-sm-column { + flex-direction: column !important + } + + .flex-sm-row-reverse { + flex-direction: row-reverse !important + } + + .flex-sm-column-reverse { + flex-direction: column-reverse !important + } + + .flex-sm-grow-0 { + flex-grow: 0 !important + } + + .flex-sm-grow-1 { + flex-grow: 1 !important + } + + .flex-sm-shrink-0 { + flex-shrink: 0 !important + } + + .flex-sm-shrink-1 { + flex-shrink: 1 !important + } + + .flex-sm-wrap { + flex-wrap: wrap !important + } + + .flex-sm-nowrap { + flex-wrap: nowrap !important + } + + .flex-sm-wrap-reverse { + flex-wrap: wrap-reverse !important + } + + .gap-sm-0 { + gap: 0 !important + } + + .gap-sm-1 { + gap: .25rem !important + } + + .gap-sm-2 { + gap: .5rem !important + } + + .gap-sm-3 { + gap: 1rem !important + } + + .gap-sm-4 { + gap: 1.5rem !important + } + + .gap-sm-5 { + gap: 3rem !important + } + + .justify-content-sm-start { + justify-content: flex-start !important + } + + .justify-content-sm-end { + justify-content: flex-end !important + } + + .justify-content-sm-center { + justify-content: center !important + } + + .justify-content-sm-between { + justify-content: space-between !important + } + + .justify-content-sm-around { + justify-content: space-around !important + } + + .justify-content-sm-evenly { + justify-content: space-evenly !important + } + + .align-items-sm-start { + align-items: flex-start !important + } + + .align-items-sm-end { + align-items: flex-end !important + } + + .align-items-sm-center { + align-items: center !important + } + + .align-items-sm-baseline { + align-items: baseline !important + } + + .align-items-sm-stretch { + align-items: stretch !important + } + + .align-content-sm-start { + align-content: flex-start !important + } + + .align-content-sm-end { + align-content: flex-end !important + } + + .align-content-sm-center { + align-content: center !important + } + + .align-content-sm-between { + align-content: space-between !important + } + + .align-content-sm-around { + align-content: space-around !important + } + + .align-content-sm-stretch { + align-content: stretch !important + } + + .align-self-sm-auto { + align-self: auto !important + } + + .align-self-sm-start { + align-self: flex-start !important + } + + .align-self-sm-end { + align-self: flex-end !important + } + + .align-self-sm-center { + align-self: center !important + } + + .align-self-sm-baseline { + align-self: baseline !important + } + + .align-self-sm-stretch { + align-self: stretch !important + } + + .order-sm-first { + order: -1 !important + } + + .order-sm-0 { + order: 0 !important + } + + .order-sm-1 { + order: 1 !important + } + + .order-sm-2 { + order: 2 !important + } + + .order-sm-3 { + order: 3 !important + } + + .order-sm-4 { + order: 4 !important + } + + .order-sm-5 { + order: 5 !important + } + + .order-sm-last { + order: 6 !important + } + + .m-sm-0 { + margin: 0 !important + } + + .m-sm-1 { + margin: .25rem !important + } + + .m-sm-2 { + margin: .5rem !important + } + + .m-sm-3 { + margin: 1rem !important + } + + .m-sm-4 { + margin: 1.5rem !important + } + + .m-sm-5 { + margin: 3rem !important + } + + .m-sm-auto { + margin: auto !important + } + + .mx-sm-0 { + margin-right: 0 !important; + margin-left: 0 !important + } + + .mx-sm-1 { + margin-right: .25rem !important; + margin-left: .25rem !important + } + + .mx-sm-2 { + margin-right: .5rem !important; + margin-left: .5rem !important + } + + .mx-sm-3 { + margin-right: 1rem !important; + margin-left: 1rem !important + } + + .mx-sm-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important + } + + .mx-sm-5 { + margin-right: 3rem !important; + margin-left: 3rem !important + } + + .mx-sm-auto { + margin-right: auto !important; + margin-left: auto !important + } + + .my-sm-0 { + margin-top: 0 !important; + margin-bottom: 0 !important + } + + .my-sm-1 { + margin-top: .25rem !important; + margin-bottom: .25rem !important + } + + .my-sm-2 { + margin-top: .5rem !important; + margin-bottom: .5rem !important + } + + .my-sm-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important + } + + .my-sm-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important + } + + .my-sm-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important + } + + .my-sm-auto { + margin-top: auto !important; + margin-bottom: auto !important + } + + .mt-sm-0 { + margin-top: 0 !important + } + + .mt-sm-1 { + margin-top: .25rem !important + } + + .mt-sm-2 { + margin-top: .5rem !important + } + + .mt-sm-3 { + margin-top: 1rem !important + } + + .mt-sm-4 { + margin-top: 1.5rem !important + } + + .mt-sm-5 { + margin-top: 3rem !important + } + + .mt-sm-auto { + margin-top: auto !important + } + + .me-sm-0 { + margin-right: 0 !important + } + + .me-sm-1 { + margin-right: .25rem !important + } + + .me-sm-2 { + margin-right: .5rem !important + } + + .me-sm-3 { + margin-right: 1rem !important + } + + .me-sm-4 { + margin-right: 1.5rem !important + } + + .me-sm-5 { + margin-right: 3rem !important + } + + .me-sm-auto { + margin-right: auto !important + } + + .mb-sm-0 { + margin-bottom: 0 !important + } + + .mb-sm-1 { + margin-bottom: .25rem !important + } + + .mb-sm-2 { + margin-bottom: .5rem !important + } + + .mb-sm-3 { + margin-bottom: 1rem !important + } + + .mb-sm-4 { + margin-bottom: 1.5rem !important + } + + .mb-sm-5 { + margin-bottom: 3rem !important + } + + .mb-sm-auto { + margin-bottom: auto !important + } + + .ms-sm-0 { + margin-left: 0 !important + } + + .ms-sm-1 { + margin-left: .25rem !important + } + + .ms-sm-2 { + margin-left: .5rem !important + } + + .ms-sm-3 { + margin-left: 1rem !important + } + + .ms-sm-4 { + margin-left: 1.5rem !important + } + + .ms-sm-5 { + margin-left: 3rem !important + } + + .ms-sm-auto { + margin-left: auto !important + } + + .p-sm-0 { + padding: 0 !important + } + + .p-sm-1 { + padding: .25rem !important + } + + .p-sm-2 { + padding: .5rem !important + } + + .p-sm-3 { + padding: 1rem !important + } + + .p-sm-4 { + padding: 1.5rem !important + } + + .p-sm-5 { + padding: 3rem !important + } + + .px-sm-0 { + padding-right: 0 !important; + padding-left: 0 !important + } + + .px-sm-1 { + padding-right: .25rem !important; + padding-left: .25rem !important + } + + .px-sm-2 { + padding-right: .5rem !important; + padding-left: .5rem !important + } + + .px-sm-3 { + padding-right: 1rem !important; + padding-left: 1rem !important + } + + .px-sm-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important + } + + .px-sm-5 { + padding-right: 3rem !important; + padding-left: 3rem !important + } + + .py-sm-0 { + padding-top: 0 !important; + padding-bottom: 0 !important + } + + .py-sm-1 { + padding-top: .25rem !important; + padding-bottom: .25rem !important + } + + .py-sm-2 { + padding-top: .5rem !important; + padding-bottom: .5rem !important + } + + .py-sm-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important + } + + .py-sm-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important + } + + .py-sm-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important + } + + .pt-sm-0 { + padding-top: 0 !important + } + + .pt-sm-1 { + padding-top: .25rem !important + } + + .pt-sm-2 { + padding-top: .5rem !important + } + + .pt-sm-3 { + padding-top: 1rem !important + } + + .pt-sm-4 { + padding-top: 1.5rem !important + } + + .pt-sm-5 { + padding-top: 3rem !important + } + + .pe-sm-0 { + padding-right: 0 !important + } + + .pe-sm-1 { + padding-right: .25rem !important + } + + .pe-sm-2 { + padding-right: .5rem !important + } + + .pe-sm-3 { + padding-right: 1rem !important + } + + .pe-sm-4 { + padding-right: 1.5rem !important + } + + .pe-sm-5 { + padding-right: 3rem !important + } + + .pb-sm-0 { + padding-bottom: 0 !important + } + + .pb-sm-1 { + padding-bottom: .25rem !important + } + + .pb-sm-2 { + padding-bottom: .5rem !important + } + + .pb-sm-3 { + padding-bottom: 1rem !important + } + + .pb-sm-4 { + padding-bottom: 1.5rem !important + } + + .pb-sm-5 { + padding-bottom: 3rem !important + } + + .ps-sm-0 { + padding-left: 0 !important + } + + .ps-sm-1 { + padding-left: .25rem !important + } + + .ps-sm-2 { + padding-left: .5rem !important + } + + .ps-sm-3 { + padding-left: 1rem !important + } + + .ps-sm-4 { + padding-left: 1.5rem !important + } + + .ps-sm-5 { + padding-left: 3rem !important + } + + .text-sm-start { + text-align: left !important + } + + .text-sm-end { + text-align: right !important + } + + .text-sm-center { + text-align: center !important + } +} + +@media (min-width: 768px) { + .float-md-start { + float: left !important + } + + .float-md-end { + float: right !important + } + + .float-md-none { + float: none !important + } + + .d-md-inline { + display: inline !important + } + + .d-md-inline-block { + display: inline-block !important + } + + .d-md-block { + display: block !important + } + + .d-md-grid { + display: grid !important + } + + .d-md-table { + display: table !important + } + + .d-md-table-row { + display: table-row !important + } + + .d-md-table-cell { + display: table-cell !important + } + + .d-md-flex { + display: flex !important + } + + .d-md-inline-flex { + display: inline-flex !important + } + + .d-md-none { + display: none !important + } + + .flex-md-fill { + flex: 1 1 auto !important + } + + .flex-md-row { + flex-direction: row !important + } + + .flex-md-column { + flex-direction: column !important + } + + .flex-md-row-reverse { + flex-direction: row-reverse !important + } + + .flex-md-column-reverse { + flex-direction: column-reverse !important + } + + .flex-md-grow-0 { + flex-grow: 0 !important + } + + .flex-md-grow-1 { + flex-grow: 1 !important + } + + .flex-md-shrink-0 { + flex-shrink: 0 !important + } + + .flex-md-shrink-1 { + flex-shrink: 1 !important + } + + .flex-md-wrap { + flex-wrap: wrap !important + } + + .flex-md-nowrap { + flex-wrap: nowrap !important + } + + .flex-md-wrap-reverse { + flex-wrap: wrap-reverse !important + } + + .gap-md-0 { + gap: 0 !important + } + + .gap-md-1 { + gap: .25rem !important + } + + .gap-md-2 { + gap: .5rem !important + } + + .gap-md-3 { + gap: 1rem !important + } + + .gap-md-4 { + gap: 1.5rem !important + } + + .gap-md-5 { + gap: 3rem !important + } + + .justify-content-md-start { + justify-content: flex-start !important + } + + .justify-content-md-end { + justify-content: flex-end !important + } + + .justify-content-md-center { + justify-content: center !important + } + + .justify-content-md-between { + justify-content: space-between !important + } + + .justify-content-md-around { + justify-content: space-around !important + } + + .justify-content-md-evenly { + justify-content: space-evenly !important + } + + .align-items-md-start { + align-items: flex-start !important + } + + .align-items-md-end { + align-items: flex-end !important + } + + .align-items-md-center { + align-items: center !important + } + + .align-items-md-baseline { + align-items: baseline !important + } + + .align-items-md-stretch { + align-items: stretch !important + } + + .align-content-md-start { + align-content: flex-start !important + } + + .align-content-md-end { + align-content: flex-end !important + } + + .align-content-md-center { + align-content: center !important + } + + .align-content-md-between { + align-content: space-between !important + } + + .align-content-md-around { + align-content: space-around !important + } + + .align-content-md-stretch { + align-content: stretch !important + } + + .align-self-md-auto { + align-self: auto !important + } + + .align-self-md-start { + align-self: flex-start !important + } + + .align-self-md-end { + align-self: flex-end !important + } + + .align-self-md-center { + align-self: center !important + } + + .align-self-md-baseline { + align-self: baseline !important + } + + .align-self-md-stretch { + align-self: stretch !important + } + + .order-md-first { + order: -1 !important + } + + .order-md-0 { + order: 0 !important + } + + .order-md-1 { + order: 1 !important + } + + .order-md-2 { + order: 2 !important + } + + .order-md-3 { + order: 3 !important + } + + .order-md-4 { + order: 4 !important + } + + .order-md-5 { + order: 5 !important + } + + .order-md-last { + order: 6 !important + } + + .m-md-0 { + margin: 0 !important + } + + .m-md-1 { + margin: .25rem !important + } + + .m-md-2 { + margin: .5rem !important + } + + .m-md-3 { + margin: 1rem !important + } + + .m-md-4 { + margin: 1.5rem !important + } + + .m-md-5 { + margin: 3rem !important + } + + .m-md-auto { + margin: auto !important + } + + .mx-md-0 { + margin-right: 0 !important; + margin-left: 0 !important + } + + .mx-md-1 { + margin-right: .25rem !important; + margin-left: .25rem !important + } + + .mx-md-2 { + margin-right: .5rem !important; + margin-left: .5rem !important + } + + .mx-md-3 { + margin-right: 1rem !important; + margin-left: 1rem !important + } + + .mx-md-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important + } + + .mx-md-5 { + margin-right: 3rem !important; + margin-left: 3rem !important + } + + .mx-md-auto { + margin-right: auto !important; + margin-left: auto !important + } + + .my-md-0 { + margin-top: 0 !important; + margin-bottom: 0 !important + } + + .my-md-1 { + margin-top: .25rem !important; + margin-bottom: .25rem !important + } + + .my-md-2 { + margin-top: .5rem !important; + margin-bottom: .5rem !important + } + + .my-md-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important + } + + .my-md-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important + } + + .my-md-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important + } + + .my-md-auto { + margin-top: auto !important; + margin-bottom: auto !important + } + + .mt-md-0 { + margin-top: 0 !important + } + + .mt-md-1 { + margin-top: .25rem !important + } + + .mt-md-2 { + margin-top: .5rem !important + } + + .mt-md-3 { + margin-top: 1rem !important + } + + .mt-md-4 { + margin-top: 1.5rem !important + } + + .mt-md-5 { + margin-top: 3rem !important + } + + .mt-md-auto { + margin-top: auto !important + } + + .me-md-0 { + margin-right: 0 !important + } + + .me-md-1 { + margin-right: .25rem !important + } + + .me-md-2 { + margin-right: .5rem !important + } + + .me-md-3 { + margin-right: 1rem !important + } + + .me-md-4 { + margin-right: 1.5rem !important + } + + .me-md-5 { + margin-right: 3rem !important + } + + .me-md-auto { + margin-right: auto !important + } + + .mb-md-0 { + margin-bottom: 0 !important + } + + .mb-md-1 { + margin-bottom: .25rem !important + } + + .mb-md-2 { + margin-bottom: .5rem !important + } + + .mb-md-3 { + margin-bottom: 1rem !important + } + + .mb-md-4 { + margin-bottom: 1.5rem !important + } + + .mb-md-5 { + margin-bottom: 3rem !important + } + + .mb-md-auto { + margin-bottom: auto !important + } + + .ms-md-0 { + margin-left: 0 !important + } + + .ms-md-1 { + margin-left: .25rem !important + } + + .ms-md-2 { + margin-left: .5rem !important + } + + .ms-md-3 { + margin-left: 1rem !important + } + + .ms-md-4 { + margin-left: 1.5rem !important + } + + .ms-md-5 { + margin-left: 3rem !important + } + + .ms-md-auto { + margin-left: auto !important + } + + .p-md-0 { + padding: 0 !important + } + + .p-md-1 { + padding: .25rem !important + } + + .p-md-2 { + padding: .5rem !important + } + + .p-md-3 { + padding: 1rem !important + } + + .p-md-4 { + padding: 1.5rem !important + } + + .p-md-5 { + padding: 3rem !important + } + + .px-md-0 { + padding-right: 0 !important; + padding-left: 0 !important + } + + .px-md-1 { + padding-right: .25rem !important; + padding-left: .25rem !important + } + + .px-md-2 { + padding-right: .5rem !important; + padding-left: .5rem !important + } + + .px-md-3 { + padding-right: 1rem !important; + padding-left: 1rem !important + } + + .px-md-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important + } + + .px-md-5 { + padding-right: 3rem !important; + padding-left: 3rem !important + } + + .py-md-0 { + padding-top: 0 !important; + padding-bottom: 0 !important + } + + .py-md-1 { + padding-top: .25rem !important; + padding-bottom: .25rem !important + } + + .py-md-2 { + padding-top: .5rem !important; + padding-bottom: .5rem !important + } + + .py-md-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important + } + + .py-md-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important + } + + .py-md-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important + } + + .pt-md-0 { + padding-top: 0 !important + } + + .pt-md-1 { + padding-top: .25rem !important + } + + .pt-md-2 { + padding-top: .5rem !important + } + + .pt-md-3 { + padding-top: 1rem !important + } + + .pt-md-4 { + padding-top: 1.5rem !important + } + + .pt-md-5 { + padding-top: 3rem !important + } + + .pe-md-0 { + padding-right: 0 !important + } + + .pe-md-1 { + padding-right: .25rem !important + } + + .pe-md-2 { + padding-right: .5rem !important + } + + .pe-md-3 { + padding-right: 1rem !important + } + + .pe-md-4 { + padding-right: 1.5rem !important + } + + .pe-md-5 { + padding-right: 3rem !important + } + + .pb-md-0 { + padding-bottom: 0 !important + } + + .pb-md-1 { + padding-bottom: .25rem !important + } + + .pb-md-2 { + padding-bottom: .5rem !important + } + + .pb-md-3 { + padding-bottom: 1rem !important + } + + .pb-md-4 { + padding-bottom: 1.5rem !important + } + + .pb-md-5 { + padding-bottom: 3rem !important + } + + .ps-md-0 { + padding-left: 0 !important + } + + .ps-md-1 { + padding-left: .25rem !important + } + + .ps-md-2 { + padding-left: .5rem !important + } + + .ps-md-3 { + padding-left: 1rem !important + } + + .ps-md-4 { + padding-left: 1.5rem !important + } + + .ps-md-5 { + padding-left: 3rem !important + } + + .text-md-start { + text-align: left !important + } + + .text-md-end { + text-align: right !important + } + + .text-md-center { + text-align: center !important + } +} + +@media (min-width: 992px) { + .float-lg-start { + float: left !important + } + + .float-lg-end { + float: right !important + } + + .float-lg-none { + float: none !important + } + + .d-lg-inline { + display: inline !important + } + + .d-lg-inline-block { + display: inline-block !important + } + + .d-lg-block { + display: block !important + } + + .d-lg-grid { + display: grid !important + } + + .d-lg-table { + display: table !important + } + + .d-lg-table-row { + display: table-row !important + } + + .d-lg-table-cell { + display: table-cell !important + } + + .d-lg-flex { + display: flex !important + } + + .d-lg-inline-flex { + display: inline-flex !important + } + + .d-lg-none { + display: none !important + } + + .flex-lg-fill { + flex: 1 1 auto !important + } + + .flex-lg-row { + flex-direction: row !important + } + + .flex-lg-column { + flex-direction: column !important + } + + .flex-lg-row-reverse { + flex-direction: row-reverse !important + } + + .flex-lg-column-reverse { + flex-direction: column-reverse !important + } + + .flex-lg-grow-0 { + flex-grow: 0 !important + } + + .flex-lg-grow-1 { + flex-grow: 1 !important + } + + .flex-lg-shrink-0 { + flex-shrink: 0 !important + } + + .flex-lg-shrink-1 { + flex-shrink: 1 !important + } + + .flex-lg-wrap { + flex-wrap: wrap !important + } + + .flex-lg-nowrap { + flex-wrap: nowrap !important + } + + .flex-lg-wrap-reverse { + flex-wrap: wrap-reverse !important + } + + .gap-lg-0 { + gap: 0 !important + } + + .gap-lg-1 { + gap: .25rem !important + } + + .gap-lg-2 { + gap: .5rem !important + } + + .gap-lg-3 { + gap: 1rem !important + } + + .gap-lg-4 { + gap: 1.5rem !important + } + + .gap-lg-5 { + gap: 3rem !important + } + + .justify-content-lg-start { + justify-content: flex-start !important + } + + .justify-content-lg-end { + justify-content: flex-end !important + } + + .justify-content-lg-center { + justify-content: center !important + } + + .justify-content-lg-between { + justify-content: space-between !important + } + + .justify-content-lg-around { + justify-content: space-around !important + } + + .justify-content-lg-evenly { + justify-content: space-evenly !important + } + + .align-items-lg-start { + align-items: flex-start !important + } + + .align-items-lg-end { + align-items: flex-end !important + } + + .align-items-lg-center { + align-items: center !important + } + + .align-items-lg-baseline { + align-items: baseline !important + } + + .align-items-lg-stretch { + align-items: stretch !important + } + + .align-content-lg-start { + align-content: flex-start !important + } + + .align-content-lg-end { + align-content: flex-end !important + } + + .align-content-lg-center { + align-content: center !important + } + + .align-content-lg-between { + align-content: space-between !important + } + + .align-content-lg-around { + align-content: space-around !important + } + + .align-content-lg-stretch { + align-content: stretch !important + } + + .align-self-lg-auto { + align-self: auto !important + } + + .align-self-lg-start { + align-self: flex-start !important + } + + .align-self-lg-end { + align-self: flex-end !important + } + + .align-self-lg-center { + align-self: center !important + } + + .align-self-lg-baseline { + align-self: baseline !important + } + + .align-self-lg-stretch { + align-self: stretch !important + } + + .order-lg-first { + order: -1 !important + } + + .order-lg-0 { + order: 0 !important + } + + .order-lg-1 { + order: 1 !important + } + + .order-lg-2 { + order: 2 !important + } + + .order-lg-3 { + order: 3 !important + } + + .order-lg-4 { + order: 4 !important + } + + .order-lg-5 { + order: 5 !important + } + + .order-lg-last { + order: 6 !important + } + + .m-lg-0 { + margin: 0 !important + } + + .m-lg-1 { + margin: .25rem !important + } + + .m-lg-2 { + margin: .5rem !important + } + + .m-lg-3 { + margin: 1rem !important + } + + .m-lg-4 { + margin: 1.5rem !important + } + + .m-lg-5 { + margin: 3rem !important + } + + .m-lg-auto { + margin: auto !important + } + + .mx-lg-0 { + margin-right: 0 !important; + margin-left: 0 !important + } + + .mx-lg-1 { + margin-right: .25rem !important; + margin-left: .25rem !important + } + + .mx-lg-2 { + margin-right: .5rem !important; + margin-left: .5rem !important + } + + .mx-lg-3 { + margin-right: 1rem !important; + margin-left: 1rem !important + } + + .mx-lg-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important + } + + .mx-lg-5 { + margin-right: 3rem !important; + margin-left: 3rem !important + } + + .mx-lg-auto { + margin-right: auto !important; + margin-left: auto !important + } + + .my-lg-0 { + margin-top: 0 !important; + margin-bottom: 0 !important + } + + .my-lg-1 { + margin-top: .25rem !important; + margin-bottom: .25rem !important + } + + .my-lg-2 { + margin-top: .5rem !important; + margin-bottom: .5rem !important + } + + .my-lg-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important + } + + .my-lg-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important + } + + .my-lg-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important + } + + .my-lg-auto { + margin-top: auto !important; + margin-bottom: auto !important + } + + .mt-lg-0 { + margin-top: 0 !important + } + + .mt-lg-1 { + margin-top: .25rem !important + } + + .mt-lg-2 { + margin-top: .5rem !important + } + + .mt-lg-3 { + margin-top: 1rem !important + } + + .mt-lg-4 { + margin-top: 1.5rem !important + } + + .mt-lg-5 { + margin-top: 3rem !important + } + + .mt-lg-auto { + margin-top: auto !important + } + + .me-lg-0 { + margin-right: 0 !important + } + + .me-lg-1 { + margin-right: .25rem !important + } + + .me-lg-2 { + margin-right: .5rem !important + } + + .me-lg-3 { + margin-right: 1rem !important + } + + .me-lg-4 { + margin-right: 1.5rem !important + } + + .me-lg-5 { + margin-right: 3rem !important + } + + .me-lg-auto { + margin-right: auto !important + } + + .mb-lg-0 { + margin-bottom: 0 !important + } + + .mb-lg-1 { + margin-bottom: .25rem !important + } + + .mb-lg-2 { + margin-bottom: .5rem !important + } + + .mb-lg-3 { + margin-bottom: 1rem !important + } + + .mb-lg-4 { + margin-bottom: 1.5rem !important + } + + .mb-lg-5 { + margin-bottom: 3rem !important + } + + .mb-lg-auto { + margin-bottom: auto !important + } + + .ms-lg-0 { + margin-left: 0 !important + } + + .ms-lg-1 { + margin-left: .25rem !important + } + + .ms-lg-2 { + margin-left: .5rem !important + } + + .ms-lg-3 { + margin-left: 1rem !important + } + + .ms-lg-4 { + margin-left: 1.5rem !important + } + + .ms-lg-5 { + margin-left: 3rem !important + } + + .ms-lg-auto { + margin-left: auto !important + } + + .p-lg-0 { + padding: 0 !important + } + + .p-lg-1 { + padding: .25rem !important + } + + .p-lg-2 { + padding: .5rem !important + } + + .p-lg-3 { + padding: 1rem !important + } + + .p-lg-4 { + padding: 1.5rem !important + } + + .p-lg-5 { + padding: 3rem !important + } + + .px-lg-0 { + padding-right: 0 !important; + padding-left: 0 !important + } + + .px-lg-1 { + padding-right: .25rem !important; + padding-left: .25rem !important + } + + .px-lg-2 { + padding-right: .5rem !important; + padding-left: .5rem !important + } + + .px-lg-3 { + padding-right: 1rem !important; + padding-left: 1rem !important + } + + .px-lg-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important + } + + .px-lg-5 { + padding-right: 3rem !important; + padding-left: 3rem !important + } + + .py-lg-0 { + padding-top: 0 !important; + padding-bottom: 0 !important + } + + .py-lg-1 { + padding-top: .25rem !important; + padding-bottom: .25rem !important + } + + .py-lg-2 { + padding-top: .5rem !important; + padding-bottom: .5rem !important + } + + .py-lg-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important + } + + .py-lg-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important + } + + .py-lg-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important + } + + .pt-lg-0 { + padding-top: 0 !important + } + + .pt-lg-1 { + padding-top: .25rem !important + } + + .pt-lg-2 { + padding-top: .5rem !important + } + + .pt-lg-3 { + padding-top: 1rem !important + } + + .pt-lg-4 { + padding-top: 1.5rem !important + } + + .pt-lg-5 { + padding-top: 3rem !important + } + + .pe-lg-0 { + padding-right: 0 !important + } + + .pe-lg-1 { + padding-right: .25rem !important + } + + .pe-lg-2 { + padding-right: .5rem !important + } + + .pe-lg-3 { + padding-right: 1rem !important + } + + .pe-lg-4 { + padding-right: 1.5rem !important + } + + .pe-lg-5 { + padding-right: 3rem !important + } + + .pb-lg-0 { + padding-bottom: 0 !important + } + + .pb-lg-1 { + padding-bottom: .25rem !important + } + + .pb-lg-2 { + padding-bottom: .5rem !important + } + + .pb-lg-3 { + padding-bottom: 1rem !important + } + + .pb-lg-4 { + padding-bottom: 1.5rem !important + } + + .pb-lg-5 { + padding-bottom: 3rem !important + } + + .ps-lg-0 { + padding-left: 0 !important + } + + .ps-lg-1 { + padding-left: .25rem !important + } + + .ps-lg-2 { + padding-left: .5rem !important + } + + .ps-lg-3 { + padding-left: 1rem !important + } + + .ps-lg-4 { + padding-left: 1.5rem !important + } + + .ps-lg-5 { + padding-left: 3rem !important + } + + .text-lg-start { + text-align: left !important + } + + .text-lg-end { + text-align: right !important + } + + .text-lg-center { + text-align: center !important + } +} + +@media (min-width: 1200px) { + .float-xl-start { + float: left !important + } + + .float-xl-end { + float: right !important + } + + .float-xl-none { + float: none !important + } + + .d-xl-inline { + display: inline !important + } + + .d-xl-inline-block { + display: inline-block !important + } + + .d-xl-block { + display: block !important + } + + .d-xl-grid { + display: grid !important + } + + .d-xl-table { + display: table !important + } + + .d-xl-table-row { + display: table-row !important + } + + .d-xl-table-cell { + display: table-cell !important + } + + .d-xl-flex { + display: flex !important + } + + .d-xl-inline-flex { + display: inline-flex !important + } + + .d-xl-none { + display: none !important + } + + .flex-xl-fill { + flex: 1 1 auto !important + } + + .flex-xl-row { + flex-direction: row !important + } + + .flex-xl-column { + flex-direction: column !important + } + + .flex-xl-row-reverse { + flex-direction: row-reverse !important + } + + .flex-xl-column-reverse { + flex-direction: column-reverse !important + } + + .flex-xl-grow-0 { + flex-grow: 0 !important + } + + .flex-xl-grow-1 { + flex-grow: 1 !important + } + + .flex-xl-shrink-0 { + flex-shrink: 0 !important + } + + .flex-xl-shrink-1 { + flex-shrink: 1 !important + } + + .flex-xl-wrap { + flex-wrap: wrap !important + } + + .flex-xl-nowrap { + flex-wrap: nowrap !important + } + + .flex-xl-wrap-reverse { + flex-wrap: wrap-reverse !important + } + + .gap-xl-0 { + gap: 0 !important + } + + .gap-xl-1 { + gap: .25rem !important + } + + .gap-xl-2 { + gap: .5rem !important + } + + .gap-xl-3 { + gap: 1rem !important + } + + .gap-xl-4 { + gap: 1.5rem !important + } + + .gap-xl-5 { + gap: 3rem !important + } + + .justify-content-xl-start { + justify-content: flex-start !important + } + + .justify-content-xl-end { + justify-content: flex-end !important + } + + .justify-content-xl-center { + justify-content: center !important + } + + .justify-content-xl-between { + justify-content: space-between !important + } + + .justify-content-xl-around { + justify-content: space-around !important + } + + .justify-content-xl-evenly { + justify-content: space-evenly !important + } + + .align-items-xl-start { + align-items: flex-start !important + } + + .align-items-xl-end { + align-items: flex-end !important + } + + .align-items-xl-center { + align-items: center !important + } + + .align-items-xl-baseline { + align-items: baseline !important + } + + .align-items-xl-stretch { + align-items: stretch !important + } + + .align-content-xl-start { + align-content: flex-start !important + } + + .align-content-xl-end { + align-content: flex-end !important + } + + .align-content-xl-center { + align-content: center !important + } + + .align-content-xl-between { + align-content: space-between !important + } + + .align-content-xl-around { + align-content: space-around !important + } + + .align-content-xl-stretch { + align-content: stretch !important + } + + .align-self-xl-auto { + align-self: auto !important + } + + .align-self-xl-start { + align-self: flex-start !important + } + + .align-self-xl-end { + align-self: flex-end !important + } + + .align-self-xl-center { + align-self: center !important + } + + .align-self-xl-baseline { + align-self: baseline !important + } + + .align-self-xl-stretch { + align-self: stretch !important + } + + .order-xl-first { + order: -1 !important + } + + .order-xl-0 { + order: 0 !important + } + + .order-xl-1 { + order: 1 !important + } + + .order-xl-2 { + order: 2 !important + } + + .order-xl-3 { + order: 3 !important + } + + .order-xl-4 { + order: 4 !important + } + + .order-xl-5 { + order: 5 !important + } + + .order-xl-last { + order: 6 !important + } + + .m-xl-0 { + margin: 0 !important + } + + .m-xl-1 { + margin: .25rem !important + } + + .m-xl-2 { + margin: .5rem !important + } + + .m-xl-3 { + margin: 1rem !important + } + + .m-xl-4 { + margin: 1.5rem !important + } + + .m-xl-5 { + margin: 3rem !important + } + + .m-xl-auto { + margin: auto !important + } + + .mx-xl-0 { + margin-right: 0 !important; + margin-left: 0 !important + } + + .mx-xl-1 { + margin-right: .25rem !important; + margin-left: .25rem !important + } + + .mx-xl-2 { + margin-right: .5rem !important; + margin-left: .5rem !important + } + + .mx-xl-3 { + margin-right: 1rem !important; + margin-left: 1rem !important + } + + .mx-xl-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important + } + + .mx-xl-5 { + margin-right: 3rem !important; + margin-left: 3rem !important + } + + .mx-xl-auto { + margin-right: auto !important; + margin-left: auto !important + } + + .my-xl-0 { + margin-top: 0 !important; + margin-bottom: 0 !important + } + + .my-xl-1 { + margin-top: .25rem !important; + margin-bottom: .25rem !important + } + + .my-xl-2 { + margin-top: .5rem !important; + margin-bottom: .5rem !important + } + + .my-xl-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important + } + + .my-xl-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important + } + + .my-xl-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important + } + + .my-xl-auto { + margin-top: auto !important; + margin-bottom: auto !important + } + + .mt-xl-0 { + margin-top: 0 !important + } + + .mt-xl-1 { + margin-top: .25rem !important + } + + .mt-xl-2 { + margin-top: .5rem !important + } + + .mt-xl-3 { + margin-top: 1rem !important + } + + .mt-xl-4 { + margin-top: 1.5rem !important + } + + .mt-xl-5 { + margin-top: 3rem !important + } + + .mt-xl-auto { + margin-top: auto !important + } + + .me-xl-0 { + margin-right: 0 !important + } + + .me-xl-1 { + margin-right: .25rem !important + } + + .me-xl-2 { + margin-right: .5rem !important + } + + .me-xl-3 { + margin-right: 1rem !important + } + + .me-xl-4 { + margin-right: 1.5rem !important + } + + .me-xl-5 { + margin-right: 3rem !important + } + + .me-xl-auto { + margin-right: auto !important + } + + .mb-xl-0 { + margin-bottom: 0 !important + } + + .mb-xl-1 { + margin-bottom: .25rem !important + } + + .mb-xl-2 { + margin-bottom: .5rem !important + } + + .mb-xl-3 { + margin-bottom: 1rem !important + } + + .mb-xl-4 { + margin-bottom: 1.5rem !important + } + + .mb-xl-5 { + margin-bottom: 3rem !important + } + + .mb-xl-auto { + margin-bottom: auto !important + } + + .ms-xl-0 { + margin-left: 0 !important + } + + .ms-xl-1 { + margin-left: .25rem !important + } + + .ms-xl-2 { + margin-left: .5rem !important + } + + .ms-xl-3 { + margin-left: 1rem !important + } + + .ms-xl-4 { + margin-left: 1.5rem !important + } + + .ms-xl-5 { + margin-left: 3rem !important + } + + .ms-xl-auto { + margin-left: auto !important + } + + .p-xl-0 { + padding: 0 !important + } + + .p-xl-1 { + padding: .25rem !important + } + + .p-xl-2 { + padding: .5rem !important + } + + .p-xl-3 { + padding: 1rem !important + } + + .p-xl-4 { + padding: 1.5rem !important + } + + .p-xl-5 { + padding: 3rem !important + } + + .px-xl-0 { + padding-right: 0 !important; + padding-left: 0 !important + } + + .px-xl-1 { + padding-right: .25rem !important; + padding-left: .25rem !important + } + + .px-xl-2 { + padding-right: .5rem !important; + padding-left: .5rem !important + } + + .px-xl-3 { + padding-right: 1rem !important; + padding-left: 1rem !important + } + + .px-xl-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important + } + + .px-xl-5 { + padding-right: 3rem !important; + padding-left: 3rem !important + } + + .py-xl-0 { + padding-top: 0 !important; + padding-bottom: 0 !important + } + + .py-xl-1 { + padding-top: .25rem !important; + padding-bottom: .25rem !important + } + + .py-xl-2 { + padding-top: .5rem !important; + padding-bottom: .5rem !important + } + + .py-xl-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important + } + + .py-xl-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important + } + + .py-xl-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important + } + + .pt-xl-0 { + padding-top: 0 !important + } + + .pt-xl-1 { + padding-top: .25rem !important + } + + .pt-xl-2 { + padding-top: .5rem !important + } + + .pt-xl-3 { + padding-top: 1rem !important + } + + .pt-xl-4 { + padding-top: 1.5rem !important + } + + .pt-xl-5 { + padding-top: 3rem !important + } + + .pe-xl-0 { + padding-right: 0 !important + } + + .pe-xl-1 { + padding-right: .25rem !important + } + + .pe-xl-2 { + padding-right: .5rem !important + } + + .pe-xl-3 { + padding-right: 1rem !important + } + + .pe-xl-4 { + padding-right: 1.5rem !important + } + + .pe-xl-5 { + padding-right: 3rem !important + } + + .pb-xl-0 { + padding-bottom: 0 !important + } + + .pb-xl-1 { + padding-bottom: .25rem !important + } + + .pb-xl-2 { + padding-bottom: .5rem !important + } + + .pb-xl-3 { + padding-bottom: 1rem !important + } + + .pb-xl-4 { + padding-bottom: 1.5rem !important + } + + .pb-xl-5 { + padding-bottom: 3rem !important + } + + .ps-xl-0 { + padding-left: 0 !important + } + + .ps-xl-1 { + padding-left: .25rem !important + } + + .ps-xl-2 { + padding-left: .5rem !important + } + + .ps-xl-3 { + padding-left: 1rem !important + } + + .ps-xl-4 { + padding-left: 1.5rem !important + } + + .ps-xl-5 { + padding-left: 3rem !important + } + + .text-xl-start { + text-align: left !important + } + + .text-xl-end { + text-align: right !important + } + + .text-xl-center { + text-align: center !important + } +} + +@media (min-width: 1400px) { + .float-xxl-start { + float: left !important + } + + .float-xxl-end { + float: right !important + } + + .float-xxl-none { + float: none !important + } + + .d-xxl-inline { + display: inline !important + } + + .d-xxl-inline-block { + display: inline-block !important + } + + .d-xxl-block { + display: block !important + } + + .d-xxl-grid { + display: grid !important + } + + .d-xxl-table { + display: table !important + } + + .d-xxl-table-row { + display: table-row !important + } + + .d-xxl-table-cell { + display: table-cell !important + } + + .d-xxl-flex { + display: flex !important + } + + .d-xxl-inline-flex { + display: inline-flex !important + } + + .d-xxl-none { + display: none !important + } + + .flex-xxl-fill { + flex: 1 1 auto !important + } + + .flex-xxl-row { + flex-direction: row !important + } + + .flex-xxl-column { + flex-direction: column !important + } + + .flex-xxl-row-reverse { + flex-direction: row-reverse !important + } + + .flex-xxl-column-reverse { + flex-direction: column-reverse !important + } + + .flex-xxl-grow-0 { + flex-grow: 0 !important + } + + .flex-xxl-grow-1 { + flex-grow: 1 !important + } + + .flex-xxl-shrink-0 { + flex-shrink: 0 !important + } + + .flex-xxl-shrink-1 { + flex-shrink: 1 !important + } + + .flex-xxl-wrap { + flex-wrap: wrap !important + } + + .flex-xxl-nowrap { + flex-wrap: nowrap !important + } + + .flex-xxl-wrap-reverse { + flex-wrap: wrap-reverse !important + } + + .gap-xxl-0 { + gap: 0 !important + } + + .gap-xxl-1 { + gap: .25rem !important + } + + .gap-xxl-2 { + gap: .5rem !important + } + + .gap-xxl-3 { + gap: 1rem !important + } + + .gap-xxl-4 { + gap: 1.5rem !important + } + + .gap-xxl-5 { + gap: 3rem !important + } + + .justify-content-xxl-start { + justify-content: flex-start !important + } + + .justify-content-xxl-end { + justify-content: flex-end !important + } + + .justify-content-xxl-center { + justify-content: center !important + } + + .justify-content-xxl-between { + justify-content: space-between !important + } + + .justify-content-xxl-around { + justify-content: space-around !important + } + + .justify-content-xxl-evenly { + justify-content: space-evenly !important + } + + .align-items-xxl-start { + align-items: flex-start !important + } + + .align-items-xxl-end { + align-items: flex-end !important + } + + .align-items-xxl-center { + align-items: center !important + } + + .align-items-xxl-baseline { + align-items: baseline !important + } + + .align-items-xxl-stretch { + align-items: stretch !important + } + + .align-content-xxl-start { + align-content: flex-start !important + } + + .align-content-xxl-end { + align-content: flex-end !important + } + + .align-content-xxl-center { + align-content: center !important + } + + .align-content-xxl-between { + align-content: space-between !important + } + + .align-content-xxl-around { + align-content: space-around !important + } + + .align-content-xxl-stretch { + align-content: stretch !important + } + + .align-self-xxl-auto { + align-self: auto !important + } + + .align-self-xxl-start { + align-self: flex-start !important + } + + .align-self-xxl-end { + align-self: flex-end !important + } + + .align-self-xxl-center { + align-self: center !important + } + + .align-self-xxl-baseline { + align-self: baseline !important + } + + .align-self-xxl-stretch { + align-self: stretch !important + } + + .order-xxl-first { + order: -1 !important + } + + .order-xxl-0 { + order: 0 !important + } + + .order-xxl-1 { + order: 1 !important + } + + .order-xxl-2 { + order: 2 !important + } + + .order-xxl-3 { + order: 3 !important + } + + .order-xxl-4 { + order: 4 !important + } + + .order-xxl-5 { + order: 5 !important + } + + .order-xxl-last { + order: 6 !important + } + + .m-xxl-0 { + margin: 0 !important + } + + .m-xxl-1 { + margin: .25rem !important + } + + .m-xxl-2 { + margin: .5rem !important + } + + .m-xxl-3 { + margin: 1rem !important + } + + .m-xxl-4 { + margin: 1.5rem !important + } + + .m-xxl-5 { + margin: 3rem !important + } + + .m-xxl-auto { + margin: auto !important + } + + .mx-xxl-0 { + margin-right: 0 !important; + margin-left: 0 !important + } + + .mx-xxl-1 { + margin-right: .25rem !important; + margin-left: .25rem !important + } + + .mx-xxl-2 { + margin-right: .5rem !important; + margin-left: .5rem !important + } + + .mx-xxl-3 { + margin-right: 1rem !important; + margin-left: 1rem !important + } + + .mx-xxl-4 { + margin-right: 1.5rem !important; + margin-left: 1.5rem !important + } + + .mx-xxl-5 { + margin-right: 3rem !important; + margin-left: 3rem !important + } + + .mx-xxl-auto { + margin-right: auto !important; + margin-left: auto !important + } + + .my-xxl-0 { + margin-top: 0 !important; + margin-bottom: 0 !important + } + + .my-xxl-1 { + margin-top: .25rem !important; + margin-bottom: .25rem !important + } + + .my-xxl-2 { + margin-top: .5rem !important; + margin-bottom: .5rem !important + } + + .my-xxl-3 { + margin-top: 1rem !important; + margin-bottom: 1rem !important + } + + .my-xxl-4 { + margin-top: 1.5rem !important; + margin-bottom: 1.5rem !important + } + + .my-xxl-5 { + margin-top: 3rem !important; + margin-bottom: 3rem !important + } + + .my-xxl-auto { + margin-top: auto !important; + margin-bottom: auto !important + } + + .mt-xxl-0 { + margin-top: 0 !important + } + + .mt-xxl-1 { + margin-top: .25rem !important + } + + .mt-xxl-2 { + margin-top: .5rem !important + } + + .mt-xxl-3 { + margin-top: 1rem !important + } + + .mt-xxl-4 { + margin-top: 1.5rem !important + } + + .mt-xxl-5 { + margin-top: 3rem !important + } + + .mt-xxl-auto { + margin-top: auto !important + } + + .me-xxl-0 { + margin-right: 0 !important + } + + .me-xxl-1 { + margin-right: .25rem !important + } + + .me-xxl-2 { + margin-right: .5rem !important + } + + .me-xxl-3 { + margin-right: 1rem !important + } + + .me-xxl-4 { + margin-right: 1.5rem !important + } + + .me-xxl-5 { + margin-right: 3rem !important + } + + .me-xxl-auto { + margin-right: auto !important + } + + .mb-xxl-0 { + margin-bottom: 0 !important + } + + .mb-xxl-1 { + margin-bottom: .25rem !important + } + + .mb-xxl-2 { + margin-bottom: .5rem !important + } + + .mb-xxl-3 { + margin-bottom: 1rem !important + } + + .mb-xxl-4 { + margin-bottom: 1.5rem !important + } + + .mb-xxl-5 { + margin-bottom: 3rem !important + } + + .mb-xxl-auto { + margin-bottom: auto !important + } + + .ms-xxl-0 { + margin-left: 0 !important + } + + .ms-xxl-1 { + margin-left: .25rem !important + } + + .ms-xxl-2 { + margin-left: .5rem !important + } + + .ms-xxl-3 { + margin-left: 1rem !important + } + + .ms-xxl-4 { + margin-left: 1.5rem !important + } + + .ms-xxl-5 { + margin-left: 3rem !important + } + + .ms-xxl-auto { + margin-left: auto !important + } + + .p-xxl-0 { + padding: 0 !important + } + + .p-xxl-1 { + padding: .25rem !important + } + + .p-xxl-2 { + padding: .5rem !important + } + + .p-xxl-3 { + padding: 1rem !important + } + + .p-xxl-4 { + padding: 1.5rem !important + } + + .p-xxl-5 { + padding: 3rem !important + } + + .px-xxl-0 { + padding-right: 0 !important; + padding-left: 0 !important + } + + .px-xxl-1 { + padding-right: .25rem !important; + padding-left: .25rem !important + } + + .px-xxl-2 { + padding-right: .5rem !important; + padding-left: .5rem !important + } + + .px-xxl-3 { + padding-right: 1rem !important; + padding-left: 1rem !important + } + + .px-xxl-4 { + padding-right: 1.5rem !important; + padding-left: 1.5rem !important + } + + .px-xxl-5 { + padding-right: 3rem !important; + padding-left: 3rem !important + } + + .py-xxl-0 { + padding-top: 0 !important; + padding-bottom: 0 !important + } + + .py-xxl-1 { + padding-top: .25rem !important; + padding-bottom: .25rem !important + } + + .py-xxl-2 { + padding-top: .5rem !important; + padding-bottom: .5rem !important + } + + .py-xxl-3 { + padding-top: 1rem !important; + padding-bottom: 1rem !important + } + + .py-xxl-4 { + padding-top: 1.5rem !important; + padding-bottom: 1.5rem !important + } + + .py-xxl-5 { + padding-top: 3rem !important; + padding-bottom: 3rem !important + } + + .pt-xxl-0 { + padding-top: 0 !important + } + + .pt-xxl-1 { + padding-top: .25rem !important + } + + .pt-xxl-2 { + padding-top: .5rem !important + } + + .pt-xxl-3 { + padding-top: 1rem !important + } + + .pt-xxl-4 { + padding-top: 1.5rem !important + } + + .pt-xxl-5 { + padding-top: 3rem !important + } + + .pe-xxl-0 { + padding-right: 0 !important + } + + .pe-xxl-1 { + padding-right: .25rem !important + } + + .pe-xxl-2 { + padding-right: .5rem !important + } + + .pe-xxl-3 { + padding-right: 1rem !important + } + + .pe-xxl-4 { + padding-right: 1.5rem !important + } + + .pe-xxl-5 { + padding-right: 3rem !important + } + + .pb-xxl-0 { + padding-bottom: 0 !important + } + + .pb-xxl-1 { + padding-bottom: .25rem !important + } + + .pb-xxl-2 { + padding-bottom: .5rem !important + } + + .pb-xxl-3 { + padding-bottom: 1rem !important + } + + .pb-xxl-4 { + padding-bottom: 1.5rem !important + } + + .pb-xxl-5 { + padding-bottom: 3rem !important + } + + .ps-xxl-0 { + padding-left: 0 !important + } + + .ps-xxl-1 { + padding-left: .25rem !important + } + + .ps-xxl-2 { + padding-left: .5rem !important + } + + .ps-xxl-3 { + padding-left: 1rem !important + } + + .ps-xxl-4 { + padding-left: 1.5rem !important + } + + .ps-xxl-5 { + padding-left: 3rem !important + } + + .text-xxl-start { + text-align: left !important + } + + .text-xxl-end { + text-align: right !important + } + + .text-xxl-center { + text-align: center !important + } +} + +@media (min-width: 1200px) { + .fs-1 { + font-size: 2.5rem !important + } + + .fs-2 { + font-size: 2rem !important + } + + .fs-3 { + font-size: 1.75rem !important + } + + .fs-4 { + font-size: 1.5rem !important + } +} + +@media print { + .d-print-inline { + display: inline !important + } + + .d-print-inline-block { + display: inline-block !important + } + + .d-print-block { + display: block !important + } + + .d-print-grid { + display: grid !important + } + + .d-print-table { + display: table !important + } + + .d-print-table-row { + display: table-row !important + } + + .d-print-table-cell { + display: table-cell !important + } + + .d-print-flex { + display: flex !important + } + + .d-print-inline-flex { + display: inline-flex !important + } + + .d-print-none { + display: none !important + } +} diff --git a/app/static/js/fillword.js b/app/static/js/fillword.js new file mode 100644 index 0000000..3e3fbd9 --- /dev/null +++ b/app/static/js/fillword.js @@ -0,0 +1,29 @@ +isRead = true; +isChoose = true; +var reader = window.speechSynthesis; // 全局定义朗读者,以便朗读和暂停 + +function getWord(){ + var word = window.getSelection?window.getSelection():document.selection.createRange().text; + return word; +} +function fillinWord(){ + var word = getWord(); + if (isRead) read(word); + if (!isChoose) return; + var element = document.getElementById("selected-words"); + element.value = element.value + " " + word; +} +document.getElementById("text-content").addEventListener("click", fillinWord, false); +function read(s){ + var msg = new SpeechSynthesisUtterance(s); + reader.speak(msg); +} +function onReadClick(){ + isRead = !isRead; + if(!isRead){ + reader.cancel(); + } +} +function onChooseClick(){ + isChoose = !isChoose; +} \ No newline at end of file diff --git a/app/static/js/highlight.js b/app/static/js/highlight.js new file mode 100644 index 0000000..2e0d84a --- /dev/null +++ b/app/static/js/highlight.js @@ -0,0 +1,95 @@ +var isHighlight = true; + +function cancelBtnHandler() { + cancel_highLight(); + document.getElementById("text-content").removeEventListener("click", fillinWord, false); + document.getElementById("text-content").removeEventListener("touchstart", fillinWord, false); + document.getElementById("text-content").addEventListener("click", fillinWord2, false); + document.getElementById("text-content").addEventListener("touchstart", fillinWord2, false); +} + +function showBtnHandler() { + document.getElementById("text-content").removeEventListener("click", fillinWord2, false); + document.getElementById("text-content").removeEventListener("touchstart", fillinWord2, false); + document.getElementById("text-content").addEventListener("click", fillinWord, false); + document.getElementById("text-content").addEventListener("touchstart", fillinWord, false); + highLight(); +} + +function getWord() { + var word = window.getSelection ? window.getSelection() : document.selection.createRange().text; + return word; +} + +function highLight() { + if(!isHighlight) return; + var txt = document.getElementById("article").innerText; + var sel_word1 = document.getElementById("selected-words"); + var sel_word2 = document.getElementById("selected-words2"); + if (sel_word1 != null) { + var list = sel_word1.value.split(" "); + for (var i = 0; i < list.length; ++i) { + list[i] = list[i].replace(/(^\s*)|(\s*$)/g, ""); + if (list[i] != "" && "".indexOf(list[i]) == -1 && "".indexOf(list[i]) == -1) { + txt = txt.replace(new RegExp(list[i], "g"), "" + list[i] + ""); + } + } + } + if (sel_word2 != null) { + var list2 = sel_word2.value.split(" "); + for (var i = 0; i < list2.length; ++i) { + list2[i] = list2[i].replace(/(^\s*)|(\s*$)/g, ""); + if (list2[i] != "" && "".indexOf(list2[i]) == -1 && "".indexOf(list2[i]) == -1) { + txt = txt.replace(new RegExp(list2[i], "g"), "" + list2[i] + ""); + } + } + } + document.getElementById("article").innerHTML = txt; +} + +function cancel_highLight() { + var txt = document.getElementById("article").innerText; + var sel_word1 = document.getElementById("selected-words"); + var sel_word2 = document.getElementById("selected-words2"); + if (sel_word1 != null) { + var list = sel_word1.value.split(" "); + for (var i = 0; i < list.length; ++i) { + list[i] = list[i].replace(/(^\s*)|(\s*$)/g, ""); + if (list[i] != "") { + txt = txt.replace("" + list[i] + "", "list[i]"); + } + } + } + if (sel_word2 != null) { + var list2 = sel_word1.value.split(" "); + for (var i = 0; i < list2.length; ++i) { + var list2 = sel_word2.value.split(" "); + list2[i] = list2[i].replace(/(^\s*)|(\s*$)/g, ""); + if (list2[i] != "") { + txt = txt.replace("" + list[i] + "", "list[i]"); + } + } + } + document.getElementById("article").innerHTML = txt; +} + +function fillinWord() { + highLight(); +} + +function fillinWord2() { + cancel_highLight(); +} + +function ChangeHighlight() { + if (isHighlight) { + isHighlight = false; + cancel_highLight(); + } else { + isHighlight = true; + highLight(); + + } +} + +showBtnHandler(); diff --git a/app/static/usr/instructions.html b/app/static/usr/instructions.html new file mode 100644 index 0000000..d352523 --- /dev/null +++ b/app/static/usr/instructions.html @@ -0,0 +1,86 @@ + + + + + + 怎么用English Pal + + + + + +

本软件的宗旨是:珍惜你的时间, 提高你的获取英文信息的速度与准确度。 不管你是英语爱好者,备考的学生,还是英语老师,都能从 English Pal 中发现用处。

+ +

如果你教英语,English Pal 可以帮你掌握题目词汇规律, 提高教学质量。

+ +

如果你学英语,English Pal 可以帮你迅速提高词汇, 轻松应对各种考试。

+ +

1秒内闪电查词,告别字典。 私人定制的单词簿,永久相伴,记录奋斗岁月。

+ +

现在就试试看吧。 English Pal 期待你的捷报, English Pal 期待你的远航

+ +

使用方法

+ +

在EnglishPal主页点击成为会员链接。支付会员费后即可开始使用。

+ +

活跃会员还有机会获得英文阅读10分钟一对一指导。

+ + + + + + + + + + + + + + + + + + + + + + + + + +
截图说明
精选短文,让你窥见世界。 统计词频,让你掌握规律。
时间无价,个性化的生词簿,为你节省记背单词时间。
考试人人都怕,单词的考试分类,让你目的明确。
+ + + + + diff --git a/app/static/wordfreqapp.sql b/app/static/wordfreqapp.sql new file mode 100644 index 0000000..76bf322 --- /dev/null +++ b/app/static/wordfreqapp.sql @@ -0,0 +1,126 @@ +PRAGMA foreign_keys=OFF; +BEGIN TRANSACTION; +CREATE TABLE user(name TEXT PRIMARY KEY, password TEXT, start_date TEXT, expiry_date TEXT); +INSERT INTO user VALUES('lanhui2','l0ve1t','20190821','20190821'); +INSERT INTO user VALUES('lanhui3','l0ve1t','20190821','20190821'); +INSERT INTO user VALUES('lanhui','l0ve1t','20190821','20220821'); +INSERT INTO user VALUES('lanhui4','l0vet','20190821','20190821'); +INSERT INTO user VALUES('lanhui5','l0veit','20190821','20190821'); +INSERT INTO user VALUES('lanhui6','l0ve1t','20190821','20190821'); +INSERT INTO user VALUES('lanhui8','l0ve1t','20190821','20190821'); +INSERT INTO user VALUES('lanhui9','l0ve1t','20190821','20190821'); +INSERT INTO user VALUES('lanhui0','l0ve1t','20190821','20190821'); +INSERT INTO user VALUES('lanhui10','l0ve1t','20190821','20190821'); +INSERT INTO user VALUES('lanhui11','l0ve1t','20190821','20190821'); +INSERT INTO user VALUES('lanhui7','l0ve1t','20190821','20190821'); +INSERT INTO user VALUES('lanhui1','l0ve1t','20190821','20190821'); +INSERT INTO user VALUES('winkong','WIN19910713','20190821','20190821'); +INSERT INTO user VALUES('lanhui12','l0ve1t','20190821','20190821'); +INSERT INTO user VALUES('lanhui13','l0ve1t','20190821','20190821'); +INSERT INTO user VALUES('lanhui14','l0ve1t','20190821','20190821'); +INSERT INTO user VALUES('Lanhui16','l0ve1t','20190821','20190821'); +INSERT INTO user VALUES('Lanhui17','l0ve1t','20190822','20190822'); +INSERT INTO user VALUES('lanhui18','l0ve1t','20190822','20190822'); +INSERT INTO user VALUES('lanhui19','l0ve1t','20190822','20190822'); +INSERT INTO user VALUES('lanhui20','l0ve1t','20190822','20190822'); +INSERT INTO user VALUES('lanhui21','l0ve1t','20190823','20190823'); +INSERT INTO user VALUES('lanhui22','l0ve1t','20190823','20190823'); +INSERT INTO user VALUES('13802399652','123123','20190823','20190823'); +INSERT INTO user VALUES('lanhui23','l0ve1t','20190823','20190823'); +INSERT INTO user VALUES('lanhui24','l0ve1t','20190824','20190824'); +INSERT INTO user VALUES('lanhui30','l0ve1t','20190830','20190830'); +INSERT INTO user VALUES('lanhui96','l0ve1t','20190906','20190906'); +INSERT INTO user VALUES('lanhui99','l0ve1t','20190909','20190909'); +INSERT INTO user VALUES('lanhui912','l0ve1t','20190912','20190912'); +INSERT INTO user VALUES('hexujie','123456','20190912','20190912'); +INSERT INTO user VALUES('lanhui913','l0ve1t','20190913','20190913'); +INSERT INTO user VALUES('lanhui914','l0ve1t','20190913','20190913'); +INSERT INTO user VALUES('lanhui915','l0ve1t','20190913','20190913'); +INSERT INTO user VALUES('lanhui913b','l0ve1t','20190913','20190913'); +INSERT INTO user VALUES('lanhui913c','l0ve1t','20190913','20190913'); +INSERT INTO user VALUES('lanhui917','l0ve1t','20190917','20190917'); +INSERT INTO user VALUES('13868989715','123456','20190920','20191220'); +INSERT INTO user VALUES('lanhui919','l0ve1t','20190920','20190920'); +INSERT INTO user VALUES('cqh','fangjie','20190920','20200320'); +INSERT INTO user VALUES('lanhui924','l0ve1t','20190924','20190924'); +INSERT INTO user VALUES('ValuedCustomer','l0ve1t','20190928','20190928'); +INSERT INTO user VALUES('lanhui1025','l0ve1t','20191025','20191025'); +INSERT INTO user VALUES('cool','test','20191025','20191025'); +INSERT INTO user VALUES('lanhui1025b','l0ve1t','20191025','20191025'); +INSERT INTO user VALUES('lanhui20210428','l0ve1t','20210428','20211230'); +INSERT INTO user VALUES('laijingtao','l0ve1t','20210428','20211230'); +INSERT INTO user VALUES('13173817032','123456','20210510','20211230'); +INSERT INTO user VALUES('984472450','984472450','20210510','20211230'); +INSERT INTO user VALUES('1292164003@qq.com','ljj123','20210510','20211230'); +INSERT INTO user VALUES('0987654321','Ca11MeLW!','20210516','20211230'); +INSERT INTO user VALUES('17858992909','123456','20210517','20211230'); +INSERT INTO user VALUES('98765','98765','20210519','20211230'); +INSERT INTO user VALUES('1359178602@qq.com','123456','20210520','20211230'); +INSERT INTO user VALUES('214660032@qq.com','ZHUWENQI','20210526','20211230'); +INSERT INTO user VALUES('admin@qq.com','‘ or ‘1’=‘1’','20210527','20211230'); +INSERT INTO user VALUES('1021844583','GGMU1234','20210610','20211230'); +INSERT INTO user VALUES('CZY_chenzhiyuan@outlook.com','Ca11MeCZY!','20210622','20211230'); +INSERT INTO user VALUES('chenzhiyuan0920@gmail.com','Ca11MeCZY!','20210622','20211230'); +INSERT INTO user VALUES('zwq','123456','20210622','20211230'); +INSERT INTO user VALUES('lanhui713','l0ve1t','20210713','20211230'); +CREATE TABLE IF NOT EXISTS "article" ( + "article_id" INTEGER PRIMARY KEY AUTOINCREMENT, + "text" TEXT, + "source" TEXT, + "date" TEXT, + "level" TEXT, + "question" TEXT +); +INSERT INTO article VALUES(1,replace('British Prime Minister Boris Johnson walks towards a voting station during the Brexit referendum in Britain, June 23, 2016. (Photo: EPA-EFE)\n\nLONDON – British Prime Minister Boris Johnson said Thursday he will likely ask Parliament to approve an election as part of an effort to break a Brexit deadlock.\n\nIt is not clear if the vote, which Johnson wants to hold on Dec. 12, will take place as opposition lawmakers must also back the move.\n\nThey are expected to vote on the measure on Monday. \n\nJohnson''s announcement comes ahead of an expected decision Friday from the European Union over whether to delay Britain''s exit from the bloc for three months. \n\nBritain''s leader has been steadfastly opposed to any extension to the nation''s scheduled Oct. 31 departure date from the EU, although in a letter to the leader of the opposition Labour Party this week he said he would accept a short technical postponement, "say to 15 or 30 November," to allow lawmakers to implement an EU withdrawal bill. \n\nJohnson''s decision to offer to call an election follows lawmakers'' rejection of his plan to rush through an EU exit bill that runs to hundreds of pages in just three days. They want more time to scrutinize the legislation and to make sure it does not leave the door open to a possible "no-deal" Brexit during future exit negotiations with the EU that will run through next year. A "no-deal" Brexit could dramatically harm Britain''s economy. \n\nThe prime minister was forced to ask for an extension to Britain''s EU departure date after Britain''s Parliament passed a law to ward off the threat of a "no-deal" Brexit.\n\nJohnson has repeatedly pledged to finalize the first stage, a transition deal, of Britain''s EU divorce battle by Oct. 31. A second stage will involve negotiating its future relationship with the EU on trade, security and other salient issues.\n','\n',char(10)),'https://www.usatoday.com/story/news/world/2019/10/24/brexit-boris-johnson-eu-extension-withdrawal-deal/4084970002/','24 Oct 2019','4',replace('QUESTION\n\n1. A no-deal Brexit will harm UK.\n\nANSWER\n\n1. F','\n',char(10))); +INSERT INTO article VALUES(2,replace('Thank you very much. We have a Cabinet meeting. We’ll have a few questions after grace. And, if you would, Ben, please do the honors.\n\nTHE PRESIDENT: All right, thank you, Ben. That was a great job. Appreciate it.\n\nThe economy is doing fantastically well. It’s getting very close to another record. We’ve had many records since we won office. We’re getting very close to another record. I don’t know if anybody saw it: The household median income for eight years of President Bush, it rose $400. For eight years of President Obama, it rose $975. And for two and half years of President Trump — they have it down as two and a half years — it rose $5,000, not including $2,000 for taxes. So it rose, let’s say, $7,000. So in two and a half years, we’re up $7,000, compared to $1,000, compared to $400. And that’s for eight years and eight years.\n\nThat’s a number that just came out, but that’s a number that I don’t know how there could be any dispute or any — I’ve never heard a number like that, meaning the economy is doing fantastically well.\n\nWe need — for our farmers, our manufacturers, for, frankly, unions and non-unions, we need USMCA to be voted on. If it’s voted on, it’ll pass. It’s up to Nancy Pelosi to put it up. If she puts it up, it’s going to pass. It’s going to be very bipartisan. It’s something that’s very much needed. It’ll be hundreds of thousands of jobs.\n','\n',char(10)),'https://www.whitehouse.gov/briefings-statements/remarks-president-trump-cabinet-meeting-15/','21 Oct 2019','3',replace('QUESTION\n\n1. Who did Trump ask to do the honors?\n\n','\n',char(10))); +INSERT INTO article VALUES(3,'And to all the extraordinary leaders and innovators gathered here from all across America and all around the world — men and women who are share — who share our vision for human exploration, for American and worldwide innovation, carrying us back to the vast expanse of space: It is my great honor to welcome all of you to this incredible gathering, celebrating the power of the past and the promise of the future, the Opening Ceremony of the 70th International Astronautical Congress. Welcome to Washington, D.C. (Applause.)','https://www.whitehouse.gov/briefings-statements/remarks-vice-president-pence-2019-international-astronautical-congress-opening-ceremony/','21 Oct 2019','3',replace('ANSWER\n\n1. Washington D.C.\n','\n',char(10))); +INSERT INTO article VALUES(4,replace('Hitchhikers in the Bathroom\n\nImagine this. You step up to the sink, wet your toothbrush, and\nbegin cleaning your pearly whites. Out of the corner of your eye,\nyou see something moving on the wall. Suddenly, you realize\nyou’re not alone in the bathroom. Your heart pounding, you turn\ntoward the tiny intruder to get a better look.\n\nYou’re horrified to see that it has eight legs, and a pair of\noversized pincers on its front end. Is it some kind of miniature\noctopus, or a bizarre crab? Is it going to sting you?\n\nActually, it’s a bug, and it’s no more harmful to you than a\nhousefly. This tiny bathroom bug is called a\npseudoscorpion (SOO-doh- SCOR-pee-uhn). But don’t be fooled by\nits name. It’s not really a scorpion; it’s just a relative. The\npseudoscorpion is a kind of arachnid (uh-RAK-nid), which means it\nis closely related to spiders, scorpions, and mites. Like\nscorpions, pseudoscorpions have a segmented body and two enormous\npincers. But pseudoscorpions lack the curved stinger that all\ntrue scorpions have.\n\nPseudoscorpions usually live outside in mulch, under tree bark,\nand in leaf litter. So how do they end up in the bathroom? They\nuse those pincer- like claws to hitch a ride on other bugs, such\nas flies and beetles. When these insects come in, so do the\npseudoscorpions - attached to their legs!\n\nThese tiny arachnids prefer moist places. Since the bathroom\ntends to be humid after bathing and showering, it’s a likely\nplace to find them. But they are easily overlooked. Most\npseudoscorpions are only about two to eight millimeters long.\n\nPseudoscorpions don’t bite or sting humans, and they can even be\nhelpful. These bugs feed on common household pests, such as\ncarpet beetle larvae, ants, mites, and small flies. Welcoming\nthis hitchhiker into your home may mean there are fewer household\npests to “bug” you!','\n',char(10)),'Liana Mahoney','27 Oct 2019','2',replace('QUESTION\n\n1. If you wanted to find a pseudoscorpion outdoors, where would you look?\n\n2. How can pseudoscorpions be helpful to humans?\n\nANSWER\n\nNone provided.\n','\n',char(10))); +INSERT INTO article VALUES(5,replace('Pentagon taps Microsoft for $10B cloud contract after Trump''s slams on Amazon\n\nThe Pentagon on Friday chose Microsoft over Amazon to provide\ncloud computing services potentially worth $10 billion after\nPresident Donald Trump and members of Congress complained the\ncompetition was stacked in Amazon''s favor.\n\nThe decision on the lucrative contract — which is likely to\nremain a flash point if the loser protests the decision with the\ngovernment or considers mounting a legal battle — comes just days\nafter Defense Secretary Mark Esper recused himself from the\ndecision-making process because his son works for one of the\nprevious competitors.\n\n"The acquisition process was conducted in accordance with\napplicable laws and regulations. The process cleared reviews by\nthe GAO and Court of Federal Claims," the Pentagon said in a\nstatement Friday night announcing the award. "All offerors were\ntreated fairly and evaluated consistently with the solicitation''s\nstated evaluation criteria. Prior to the award, the department\nconferred with the DOD Inspector General, which informed the\ndecision to proceed."\n\nAmazon said it was "surprised" by the decision, but declined to\nsay if it would be filing a protest.\n\n"[Amazon Web Services] is the clear leader in cloud computing,\nand a detailed assessment purely on the comparative offerings\nclearly lead to a different conclusion," a spokesperson for the\ncompany said in a statement. "We remain deeply committed to\ncontinuing to innovate for the new digital battlefield where\nsecurity, efficiency, resiliency, and scalability of resources\ncan be the difference between success and failure.”\n\nMicrosoft did not immediately have a statement to provide.\n\nIt''s unclear what impact President Donald Trump''s criticism of\nAmazon and its founder Jeff Bezos had on the final contract\ndecision. Trump allegedly told former Defense Secretary Jim\nMattis that he wanted to "screw" Amazon by denying them the\ncontract, according to a book by former Mattis aide Guy Snodgrass\nthat is set to be released next week.\n\nWhether Amazon protests will depend on what the company hears\nwhen it receives a briefing from the Pentagon on the agency''s\ndecision making on why it selected Microsoft, according to Andrew\nHunter, a former Defense Department acquisition aide and current\nsenior fellow at the Center for Strategic and International\nStudies.\n\n"If it wasn’t close, then Amazon may not protest. If it was\nclose, I think they are pretty likely to protest given all the\nunusual activity on this procurement," Hunter told POLITICO. "My\nguess is that this competition came down to price."\n\nThe winner-take-all project is intended to establish a common\ncomputing and data storage system that will allow the military to\nachieve some of its most advanced technology objectives,\nincluding integrating onto the battlefield more artificial\nintelligence capabilities, which require massive amounts of\nprocessing power and storage that are provided by a sophisticated\ncloud. The program will also allow for secure information sharing\nacross the Defense Department, so warfighting intelligence can be\nseamless shared among different platforms like drones, aircraft\nor ships.\n\nThe Joint Enterprise Defense Infrastructure program, better known\nas JEDI, could be extended for 10 years and be worth up to $10\nbillion if all contract options are exercised.\n\nBut it is almost certain that Microsoft''s selection will not be\nthe final word for a program that has been politically fraught\nand the target of a series of court challenges and other formal\nprotests.\n\n“There is really no downside to protesting, except perhaps the\nill will it might generate by causing additional delay,” said Tom\nSpoehr, the director of the Heritage Foundation’s Center for\nNational Defense. “Given all the effort that the companies have\nput into their bids, a protest would not be surprising.”\n\nThe competition went through several phases before Amazon and\nMicrosoft emerged as finalists over Oracle and IBM Corp., which\nwere among the initial bidders.\n\nOracle took the Pentagon to court in December after it was cut\nfrom the competition, alleging that the Defense Department\nunfairly limited competition by tailoring the JEDI requirements\nto Amazon''s proposed solution.\n\nOracle also claimed in its lawsuit that Deap Ubhi, a former\nPentagon employee who worked for Amazon, unfairly influenced the\ncompetition. In July, however, a federal judge ruled in favor of\nthe Pentagon and also concluded that Oracle''s initial proposal\ndid not meet the contract requirements. Oracle announced in\nAugust that it would appeal that ruling to the U.S. Court of\nAppeals for the Federal Circuit, but has not yet formally filed\nthe appeal.\n\nOracle separately filed a protest in August 2018 with the\nGovernment Accountability Office, which also concluded that the\nPentagon’s procurement process was fair.\n\nWhile Oracle has been the most vocal critic of the program, IBM\nCorp. also filed a protest with the Government Accountability\nOffice in October 2018 arguing that the Pentagon should select\nmultiple winners instead of structuring the competition as\nwinner-takes-all.\n\n"IBM has long raised serious concerns about the structure of the\nJEDI procurement," IBM spokesperson Adam Pratt said in July. "We\ncontinue to believe that the Department of Defense and our men\nand women in uniform would be best served by a multicloud\nstrategy."\n\nPresident Trump, who has been engaged in a public spat with\nAmazon founder Jeff Bezos, accusing the billionaire of using his\nownership of The Washington Post to attack him, took a personal\ninterest in the JEDI competition ahead of the contract being\nawarded.\n\nIn July he asked officials to review the contracting process\nafter both members of Congress and companies themselves\ncomplained to the president that the bidding process was not open\nand competitive.\n\n“I’m getting tremendous complaints about the contract with the\nPentagon and with Amazon,” Trump said on July 18. “Some of the\ngreatest companies in the world are complaining about it, having\nto do with Amazon and the Department of Defense, and I will be\nasking them to look at it very closely to see what’s going on.”\n\n\nThe public spat between Trump and Bezos extends beyond this\ndefense procurement. Trump has attacked the billionaire on\nTwitter for paying too little in taxes and ripping off the\nU.S. Postal Service.\n\nLawmakers on both sides of the aisle also urged the president to\nget involved to ensure the competition was fair and the Pentagon\nwould be getting the best deal possible. For example, about a\ndozen members of the House GOP caucus, who are not members of the\nHouse Armed Services Committee, sent a letter in July asking the\npresident to delay the program until the Pentagon had finished\ninvestigating the fairness of the competition.\n\nThose who serve on the committees that oversee the military,\nhowever, tend to disagree. Two Democrats — Sen. Mark\nWarner (D-Va.) and Senate Armed Services Committee ranking member\nSen. Jack Reed (D-R.I.) — wrote a similar letter to the Pentagon\nin August asking Defense Secretary Mark Esper to protect the\nprogram from political pressure and keep it moving forward. Four\nRepublican members of the House Armed Services Committee,\nincluding ranking member Mac Thornberry, also sent a letter to\nTrump in July asking the president to allow the program to\ncontinue without interference.\n\n“While it is understandable that some of the companies competing\nfor the contract are disappointed at not being selected as one of\nthe finalists, further unnecessary delays will only damage our\nsecurity and increase the cost of the contract,” the GOP\nlawmakers wrote in the letter.\n\nIn response, Defense Secretary Mark Esper announced shortly after\ntaking over the Pentagon’s top job that he was personally\nreviewing the program, saying that he wanted to get up to speed\non the major procurement through a series of learning sessions\nwith Defense officials. During a series of listening sessions,\nEsper realized how contentious the program truly was and removed\nhimself from the decision-making process because his son worked\nfor IBM. Instead, he delegated the authority to Deputy Defense\nSecretary David Norquist.\n\nFor good measure, the Pentagon''s inspector general also conducted\nits own review, which began in August. The Pentagon said it had\nconsulted with the inspector general before issuing the award and\nwas told it could move forward.\n','\n',char(10)),'https://www.politico.com/news/2019/10/25/pentagon-microsoft-cloud-trump-058083','27 Oct 2019','4',replace('QUESTION\n\nANSWER\n','\n',char(10))); +INSERT INTO article VALUES(6,replace('Microsoft Is the Surprise Winner of a $10B Pentagon Contract\n\nAmazon had long been considered the favorite for JEDI, a project to use cloud computing to modernize warfare.','\n',char(10)),'https://www.wired.com/story/microsoft-surprise-winner-dollar10b-pentagon-contract/','27 Oct 2019','4',replace('QUESTION\n\nANSWER\n','\n',char(10))); +INSERT INTO article VALUES(7,replace('Ancient stars shed light on Earth''s similarities to other planets\nNew method used to study planets'' geochemistry implies that Earth is not unique\n\nDate:\n October 17, 2019\nSource:\n University of California - Los Angeles\nSummary:\n Earth-like planets may be common in the universe, a new study implies. The team of astrophysicists and geochemists presents new evidence that the Earth is not unique.\n\n\nEarth-like planets may be common in the universe, a new UCLA study implies. The team of astrophysicists and geochemists presents new evidence that the Earth is not unique. The study was published in the journal Science on Oct. 18.\n\n"We have just raised the probability that many rocky planets are like the Earth, and there''s a very large number of rocky planets in the universe," said co-author Edward Young, UCLA professor of geochemistry and cosmochemistry.\n\nThe scientists, led by Alexandra Doyle, a UCLA graduate student of geochemistry and astrochemistry, developed a new method to analyze in detail the geochemistry of planets outside of our solar system. Doyle did so by analyzing the elements in rocks from asteroids or rocky planet fragments that orbited six white dwarf stars.\n\n"We''re studying geochemistry in rocks from other stars, which is almost unheard of," Young said.\n\n"Learning the composition of planets outside our solar system is very difficult," said co-author Hilke Schlichting, UCLA associate professor of astrophysics and planetary science. "We used the only method possible -- a method we pioneered -- to determine the geochemistry of rocks outside of the solar system."\n\nWhite dwarf stars are dense, burned-out remnants of normal stars. Their strong gravitational pull causes heavy elements like carbon, oxygen and nitrogen to sink rapidly into their interiors, where the heavy elements cannot be detected by telescopes. The closest white dwarf star Doyle studied is about 200 light-years from Earth and the farthest is 665 light-years away.\n\n"By observing these white dwarfs and the elements present in their atmosphere, we are observing the elements that are in the body that orbited the white dwarf," Doyle said. The white dwarf''s large gravitational pull shreds the asteroid or planet fragment that is orbiting it, and the material falls onto the white dwarf, she said. "Observing a white dwarf is like doing an autopsy on the contents of what it has gobbled in its solar system."\n\nThe data Doyle analyzed were collected by telescopes, mostly from the W.M. Keck Observatory in Hawaii, that space scientists had previously collected for other scientific purposes.\n\n"If I were to just look at a white dwarf star, I would expect to see hydrogen and helium," Doyle said. "But in these data, I also see other materials, such as silicon, magnesium, carbon and oxygen -- material that accreted onto the white dwarfs from bodies that were orbiting them."\n\nWhen iron is oxidized, it shares its electrons with oxygen, forming a chemical bond between them, Young said. "This is called oxidation, and you can see it when metal turns into rust," he said. "Oxygen steals electrons from iron, producing iron oxide rather than iron metal. We measured the amount of iron that got oxidized in these rocks that hit the white dwarf. We studied how much the metal rusts."\n\nRocks from the Earth, Mars and elsewhere in our solar system are similar in their chemical composition and contain a surprisingly high level of oxidized iron, Young said. "We measured the amount of iron that got oxidized in these rocks that hit the white dwarf," he said.\n\nThe sun is made mostly of hydrogen, which does the opposite of oxidizing -- hydrogen adds electrons.\n\nThe researchers said the oxidation of a rocky planet has a significant effect on its atmosphere, its core and the kind of rocks it makes on its surface. "All the chemistry that happens on the surface of the Earth can ultimately be traced back to the oxidation state of the planet," Young said. "The fact that we have oceans and all the ingredients necessary for life can be traced back to the planet being oxidized as it is. The rocks control the chemistry."\n\nUntil now, scientists have not known in any detail whether the chemistry of rocky exoplanets is similar to or very different from that of the Earth.\n\nHow similar are the rocks the UCLA team analyzed to rocks from the Earth and Mars?\n\n"Very similar," Doyle said. "They are Earth-like and Mars-like in terms of their oxidized iron. We''re finding that rocks are rocks everywhere, with very similar geophysics and geochemistry."\n\n"It''s always been a mystery why the rocks in our solar system are so oxidized," Young said. "It''s not what you expect. A question was whether this would also be true around other stars. Our study says yes. That bodes really well for looking for Earth-like planets in the universe."\n\nWhite dwarf stars are a rare environment for scientists to analyze.\n\nThe researchers studied the six most common elements in rock: iron, oxygen, silicon, magnesium, calcium and aluminum. They used mathematical calculations and formulas because scientists are unable to study actual rocks from white dwarfs. "We can determine the geochemistry of these rocks mathematically and compare these calculations with rocks that we do have from Earth and Mars," said Doyle, whose background is in geology and mathematics. "Understanding the rocks is crucial because they reveal the geochemistry and geophysics of the planet."\n\n"If extraterrestrial rocks have a similar quantity of oxidation as the Earth has, then you can conclude the planet has similar plate tectonics and similar potential for magnetic fields as the Earth, which are widely believed to be key ingredients for life," Schlichting said. "This study is a leap forward in being able to make these inferences for bodies outside our own solar system and indicates it''s very likely there are truly Earth analogs."\n\nYoung said his department has both astrophysicists and geochemists working together.\n\n"The result," he said, "is we are doing real geochemistry on rocks from outside our solar system. Most astrophysicists wouldn''t think to do this, and most geochemists wouldn''t think to ever apply this to a white dwarf."\n\nThe research was funded by NASA.\n','\n',char(10)),'https://www.sciencedaily.com/releases/2019/10/191017141052.htm','27 Oct 2019','3',replace('QUESTION\n\nANSWER\n','\n',char(10))); +INSERT INTO article VALUES(8,replace('''Artificial leaf'' successfully produces clean gas\n\nDate:\n October 21, 2019\nSource:\n University of Cambridge\nSummary:\n A widely-used gas that is currently produced from fossil fuels can instead be made by an ''artificial leaf'' that uses only sunlight, carbon dioxide and water, and which could eventually be used to develop a sustainable liquid fuel alternative to gasoline. \n','\n',char(10)),'https://www.sciencedaily.com/releases/2019/10/191021111826.htm','27 Oct 2019','2','QUESTION'); +INSERT INTO article VALUES(9,replace('VALVE PACKED FOR FRESHNESS\n\nTESCO\n/////\n\nITALIAN\nFRESH GROUND COFFEE\n\nRAINFOREST ALLIANCE\nCERTIFIED\nMinimum 30% Certified Coffee\n\nThis coffee has been blended and roasted to produce a rich, full\nbodied Italian style coffee, for thoese for like a stronger after\ndinner coffee.\n\n4\nMedium/Strong\n\n\nOur promise\n\nWe are happy to refund or replace any Tesco product which falls below\nthe high standard you expect. Just ask any member of staff. This\ndoes not affect your statutory rights.\n\nWe are here to help:\nFreephone 0800 50 55 55.\nMon-Sat, 9am-6pm.\nShop on-line at www.tesco.com\n\nFRED VERBOOM HAS WORKED AS A COFFEE CONSULTANT FOR TESTCO SINCE 2003.\nHAVING SPENT ALL OF HIS WORKING LIFE IN THE INTERNATIONAL COFFEE\nINDUSTRY AS TASTER AND BLENDER, FRED''S EXPERTISE AND KNOWLEDGE IS\nINVALUABLE TO ENSURING TESCO CAN OFFER THE BEST POSSIBLE COFFEES.\n\n<0303 3401>\n\n\nAbout Rainforest Alliance Certification:\n\nThe Rainforest Alliance Certified^TM seal guarantees that famers\nfollow sound agricultural practices that protect forests, rivers,\nsoils and wildlife, while being good community neighbours. Rainforest\nAlliance Certification also ensures that workers have just wages,\ndignified living conditions and access to education and health care.\n\nThe Rainforest Alliance engages business and consumers to conserve\nbiodiversity and ensure sustainable livelihoods by transforming\nland-use practices, business practices and consumer behaviour.\n\n\nA blend of quality beans expertly roasted to produce a full bodied,\nstronger coffee. Ideal as an after dinner coffee. Suitable for\ncafetieres, filter machines, moka pots and percolators.\n\nPreparation guidelines\nHow to make the perfect cup of coffee:\n\n\nCafetiere:\n[Omitted]\n\nFilter machine:\n[Omitted]\n\nMoka pot:\n\n* Fill the bottom part of the unit with freshly drawn cold water.\n* Insert the filter basket, fill with coffee and level the surface (do\n not overfill and/or tap down the coffee).\n* Assemble unit and brew on a medium heat for approximately 5 minutes.\n* Pour and enjoy! (Suitable for all types of moka pots and filter\n machines. Always follow manufacturer''s guidelines.)\n\n\nRoast and ground coffee.\n------------------------\nStorage\n* The flavour and aroma of coffee deteriorates once in contact with air.\n* This pack has a one way valve which allows the coffee to be packed immediately after roasting and grinding to maintain freshness.\n* Once opened, reseal the pack by rolling down the top of the bag and secure with the tab.\n* Store in a freezer, refrigerator or cool place.\n* Use within 2 weeks of opening.\n\nAdditional information\n\n* Packaged in a protective atmosphere.\n\nDISPOSAL\n\nBAG-MIXED\nMATERIAL\nNot currently recycled\n\n227g e\n\nProduce of more than one country.\nPacked in the U.K. for Tesco Stores Ltd., Cheshunt EN8 9SL, U.K.\nCopyright Tesco 2012. SC211282.\n\nBest before end:\n\nMay 2018\n\n7142 2\n07:24\n\n','\n',char(10)),replace('Source: product package\n','\n',char(10)),'29 Oct 2019','3',replace('QUESTION\n\n1. What product is the above description for?\n \nANSWER\n\n1. Coffee\n','\n',char(10))); +INSERT INTO article VALUES(10,replace('BORDER\n\nfamily Biscuitiers\n\nSINCE 1984\n\n2x\n\nCLASSIC RECIPES\n\nCOLDEN OAT GRUMBLES\n\n30g\n\n\n\nIngredients: Wheat ...\nSuitable for Vegetarians\nStore in a cool, dry place and away from direct sunlight.\nWe are happy to declare that the palm oil contained within the ingredients we buy is certified as sustainable.\n\n\n[Bar Code]\n\n\nFor best before information, see side of pack\n\nBEST BEFORE\n28 JUN 2019\n8221 18:56\n\nPlease tell us if you loved these biscuits...\nor not. Email sales@borderbiscuits.co.uk\nor write to the address below.\nBaked in Scotland by our skilled Biscuitiers\nat:\nBorder Biscuits Ltd, South Faulds Road, Lanark, Lanarkshire, SCOTLAND, ML11 7SR.\nwww.borderbiscuits.co.uk\n\n[Facebook] [Tweet]\n\nNutritional Information/UK&EU per 100g per biscuit\n--------------------------------------------------------\nEnergy\nFat\nOf which saturates\nCarbohydrate\nof which sugars\nProtein\nSalt\n','\n',char(10)),'Source: product package','29 Oct 2019','2',replace('QUESTION\n\n1. What product is the above description for?\n \nANSWER\n\n1. Biscuit.\n\n','\n',char(10))); +INSERT INTO article VALUES(11,'It must have struck most naturalists as a strange anomaly that, in the case of both animals and plants, species of the same family and even of the same genus, though agreeing closely with each other in almost their whole organisation, yet are not rarely, some of them hermaphrodites, and some of them unisexual. But if, in fact, all hermaphrodites do occasionally intercross with other individuals, the difference between hermaphrodites and unisexual species, as far as function is concerned, becomes very small. ','Charles Darwin','29 Oct 2019','4',replace('QUESTION\n\n1. What scientific field does the above passage most likely belong to?\n\nA. Biology\nB. Physics\nC. Chemistry\nD. Quantum mechanics\n\nANSWER\n\n1. A\n','\n',char(10))); +INSERT INTO article VALUES(12,replace('Playboy: Maybe we should pause and get your definition of what a computer is. How do they work?\n\nJobs: Computers are actually pretty simple. We’re sitting here on a bench in this café [for this part of the Interview]. Let’s assume that you understood only the most rudimentary of directions and you asked how to find the rest room. I would have to describe it to you in very specific and precise instructions. I might say, “Scoot sideways two meters off the bench. Stand erect. Lift left foot. Bend left knee until it is horizontal. Extend left foot and shift weight 300 centimeters forward…” and on and on. If you could interpret all those instructions 100 times faster than any other person in this café, you would appear to be a magician: You could run over and grab a milk shake and bring it back and set it on the table and snap your fingers, and I’d think you made the milk shake appear, because it was so fast relative to my perception. That’s exactly what a computer does. It takes these very, very simple-minded instructions—“Go fetch a number, add it to this number, put the result there, perceive if it’s greater than this other number”—but executes them at a rate of, let’s say, 1,000,000 per second. At 1,000,000 per second, the results appear to be magic.\n\nThat’s a simple explanation, and the point is that people really don’t have to understand how computers work. Most people have no concept of how an automatic transmission works, yet they know how to drive a car. You don’t have to study physics to understand the laws of motion to drive a car. You don’t have to understand any of this stuff to use Macintosh—but you asked. [laughs]','\n',char(10)),'reprints.longform.org/playboy-interview-steve-jobs','29 Oct 2019','3',replace('QUESTION\n\n1. Steve Jobs used "grabbing milk shake" as an analogy for what?\n\nANSWER\n\n1. For explaining how computers work.','\n',char(10))); +INSERT INTO article VALUES(13,replace('Infectious Disease Expert Discusses What We Know about the New Chinese Virus\n\nFederal disease agency director Anthony Fauci discusses the novel pathogen that has, so far, sickened hundreds in Asia and one person in the U.S.\n\nBy Tanya Lewis on January 22, 2020\n\nInfectious Disease Expert Discusses What We Know about the New Chinese Virus\n\nThe first confirmed U.S. case of a traveler infected with the virus behind China’s continuing pneumonia outbreak has health authorities on alert to prevent it from spreading. The patient—a man in his 30s—returned from the country’s city of Wuhan (where the virus appears to have originated) to his home in Snohomish County in Washington State on January 15. He developed symptoms and sought treatment from his doctor on January 19, and a day later, a real time reverse transcription-polymerase chain reaction (rRT-PCR) test confirmed he had the virus. The patient appears to be doing well and was being treated this week at a hospital in Everett, Wash., and placed in isolation out of an abundance of caution, said a spokesperson for the U.S. Centers for Disease Control and Prevention in a news briefing on Tuesday afternoon.\n\nThe virus, called 2019 novel coronavirus (2019-nCoV), is known to have infected hundreds of people so far, and Chinese authorities have now reported at least 17 deaths. It was first identified in Wuhan late last year and is believed to have jumped from animals to humans at a local seafood market that also sold other wild animal meat. Authorities have since confirmed cases of human-to-human transmission. The pathogen is a coronavirus, a member of a family of viruses that include severe acute respiratory syndrome (SARS) and Middle East respiratory syndrome (MERS), which caused major outbreaks in 2003 and 2012, respectively.\n\nCases of 2019-nCoV have been confirmed in several other countries, including Thailand, Japan and South Korea. Three U.S. airports—in San Francisco, Los Angeles and New York City—began screening travelers from Wuhan last week. Such measures have now been expanded to two more airports—in Atlanta and Chicago—and passengers traveling to the U.S. from Wuhan will be funneled to those five locations. The risk to the U.S. public is low at this time, according to the Centers for Disease Control and Prevention. But the agency says it is working closely with other health organizations to contain the virus’s spread.\nAdvertisement\n\nNational Institute of Allergy and Infectious Diseases director Anthony Fauci has been been closely following developments related to the new virus. Scientific American spoke with Fauci about 2019-nCoV’s likely mode of transmission, its similarity to other coronaviruses and the question of whether a vaccine is on the horizon.\n\n[An edited transcript of the conversation follows.]\n\nDo we know how the U.S. patient contracted the virus?\n\nHe was not in any market where there may have been an animal reservoir, and he does not recall coming into contact with someone who was ill. That’s not surprising: often people contract respiratory infections without knowing the definite exposure source. But he was in Wuhan.\n\nIs the most likely source of this virus an animal market in Wuhan?\nAdvertisement\n\nIt almost certainly came from an animal—almost certainly.\n\nDo you suspect the virus is transmitted via a respiratory route?\n\nA respiratory infection is almost certainly transmitted through droplets. Respiratory spread is a very good guess. We have not definitively proved that the virus entered through the respiratory tract, but it is highly likely. When you have symptoms of fever, cough, infiltrates in the lung, and respiratory symptoms, historically, respiratory is the route.\nnewsletter promo\n\nHow similar or different is the virus from other coronaviruses such as SARS or MERS?\n\nFirst of all, it’s a coronavirus, the same family as SARS. It has some of the same molecular homology as SARS. It’s closer to SARS than it is to MERS. But it isn’t overwhelmingly close.\nAdvertisement\n\nDo we know the mortality rate of the new virus?\n\nIt’s a moving target. It’s a rough estimate. If you look at the number of cases, it’s around 300. There have been six deaths so far. [Editor’s Note: On Wednesday, several outlets reported that Chinese authorities had announced 17 deaths, and some had cited more than 540 cases.] We’re only seeing the ones who are hospitalized. If there are asymptomatic infections, the mortality rate would be much less. Among symptomatic people, the mortality rate is around 2 percent. It was 10 percent with SARS, and 30 to 35 percent with MERS. It may be less virulent than those two or it may evolve. It’s too early to know.\n\nAren’t the symptoms of this viral infection similar to many other types of respiratory infection? How can you tell them apart?\n\nIt’s a syndromic and epidemiological association. If somebody comes into an emergency room in Washington State with a respiratory illness, and they haven’t been to China, they probably have the flu or some other virus. But if they came from Wuhan, it’s likely to be the new coronavirus. The symptoms are very common to a number of viruses, though, so [the association] is based on epidemiology [and is confirmed by the rRT-PCR test].\n\nHow are the patients with this virus being treated?\n\nIt’s mostly symptomatic treatment. There are experimental antivirals that have been used in vitro and in vivo. If the patients need antibiotics for complicating bacterial infections, you give them antibiotics. If they need to be put on a respirator, they’re put on a respirator. Most patients in China are doing well. But a proportion of them are very ill and are on respirators.\n\nHow long will it be before we have a vaccine for this virus?\n\nWe’ve already started to develop a vaccine. We got the [genetic] sequence from the Chinese. We’re partnering with a company called Moderna to develop a messenger RNA–based platform for a vaccine. We will likely have a candidate in early phase I trials for safety in about three months. That doesn’t mean we will have a vaccine ready for use in three months; even in an emergency, that would take a year or more. But we’re already on it.\n\nHow common are coronaviruses, and how often do they jump from animals to humans?\n\nCoronaviruses represent 10 to 30 percent of common colds. Over the past 18 years we’ve had three coronaviruses from animal reservoirs: SARS, MERS and now this. There could be several intermediary hosts, but at least with SARS and MERS, the primary host is thought to be a bat. We don’t know what the primary host is for this virus yet.\n\n\nABOUT THE AUTHOR(S)\nTanya Lewis\n\nTanya Lewis is an associate editor at Scientific American who covers health and medicine.\n\n\n\nAll Rights Reserved.\n','\n',char(10)),'https://www.scientificamerican.com/article/infectious-disease-expert-discusses-what-we-know-about-the-new-chinese-virus/','22 Jan 2020','4',replace('QUESTION\n\nSARS is a type of coronaviruse. Is this statement true?\n\nANSWER\n\nTrue.\n','\n',char(10))); +INSERT INTO article VALUES(14,replace('The Magic of Doing One Thing at a Time\n\nBy Tony Schwartz\n\n(Tony Schwartz is the president and CEO of The Energy Project and the author of The Way We’re Working Isn’t Working. Become a fan of The Energy Project on Facebook and connect with Tony at Twitter.com/TonySchwartz and Twitter.com/Energy_Project.)\n\nWhy is it that between 25% and 50% of people report feeling overwhelmed or burned out at work?\n\nIt’s not just the number of hours we’re working, but also the fact that we spend too many continuous hours juggling too many things at the same time.\n\nWhat we’ve lost, above all, are stopping points, finish lines and boundaries. Technology has blurred them beyond recognition. Wherever we go, our work follows us, on our digital devices, ever insistent and intrusive. It’s like an itch we can’t resist scratching, even though scratching invariably makes it worse.\n\nTell the truth: Do you answer email during conference calls (and sometimes even during calls with one other person)? Do you bring your laptop to meetings and then pretend you’re taking notes while you surf the net? Do you eat lunch at your desk? Do you make calls while you’re driving, and even send the occasional text, even though you know you shouldn’t?\n\nThe biggest cost — assuming you don’t crash — is to your productivity. In part, that’s a simple consequence of splitting your attention, so that you’re partially engaged in multiple activities but rarely fully engaged in any one. In part, it’s because when you switch away from a primary task to do something else, you’re increasing the time it takes to finish that task by an average of 25 per cent.\n\nBut most insidiously, it’s because if you’re always doing something, you’re relentlessly burning down your available reservoir of energy over the course of every day, so you have less available with every passing hour.\n\nI know this from my own experience. I get two to three times as much writing accomplished when I focus without interruption for a designated period of time and then take a real break, away from my desk. The best way for an organization to fuel higher productivity and more innovative thinking is to strongly encourage finite periods of absorbed focus, as well as shorter periods of real renewal.\n\nIf you’re a manager, here are three policies worth promoting:\n\n1. Maintain meeting discipline. Schedule meetings for 45 minutes, rather than an hour or longer, so participants can stay focused, take time afterward to reflect on what’s been discussed, and recover before the next obligation. Start all meetings at a precise time, end at a precise time, and insist that all digital devices be turned off throughout the meeting.\n\n2. Stop demanding or expecting instant responsiveness at every moment of the day. It forces your people into reactive mode, fractures their attention, and makes it difficult for them to sustain attention on their priorities. Let them turn off their email at certain times. If it’s urgent, you can call them — but that won’t happen very often.\n\n3. Encourage renewal. Create at least one time during the day when you encourage your people to stop working and take a break. Offer a midafternoon class in yoga, or meditation, organize a group walk or workout, or consider creating a renewal room where people can relax, or take a nap.\n\nIt’s also up to individuals to set their own boundaries. Consider these three behaviors for yourself:\n\n1. Do the most important thing first in the morning, preferably without interruption, for 60 to 90 minutes, with a clear start and stop time. If possible, work in a private space during this period, or with sound-reducing earphones. Finally, resist every impulse to distraction, knowing that you have a designated stopping point. The more absorbed you can get, the more productive you’ll be. When you’re done, take at least a few minutes to renew.\n\n2. Establish regular, scheduled times to think more long term, creatively, or strategically. If you don’t, you’ll constantly succumb to the tyranny of the urgent. Also, find a different environment in which to do this activity — preferably one that’s relaxed and conducive to open-ended thinking.\n\n3. Take real and regular vacations. Real means that when you’re off, you’re truly disconnecting from work. Regular means several times a year if possible, even if some are only two or three days added to a weekend. The research strongly suggests that you’ll be far healthier if you take all of your vacation time, and more productive overall.\n\nA single principle lies at the heart of all these suggestions. When you’re engaged at work, fully engage, for defined periods of time. When you’re renewing, truly renew. Make waves. Stop living your life in the gray zone.\n\n','\n',char(10)),'Harvard Business Review','27 Jan 2020','3',replace('QUESTION\n\nWhat is consequence of multi-tasking?\n\n\nANSWER\n\nOverwhelmed.\n','\n',char(10))); +INSERT INTO article VALUES(15,replace('A dreadful day\n\nby George Grossmith\n\nJune 7.—A dreadful annoyance. Met Mr. Franching, who lives at Peckham, and who is a great swell in his way. I ventured to ask him to come home to meat-tea, and take pot-luck. I did not think he would accept such a humble invitation; but he did, saying, in a most friendly way, he would rather “peck” with us than by himself. I said: “We had better get into this blue ’bus.” He replied: “No blue-bussing for me. I have had enough of the blues lately. I lost a cool ‘thou’ over the Copper Scare. Step in here.”\n\nWe drove up home in style, in a hansom-cab, and I knocked three times at the front door without getting an answer. I saw Carrie, through the panels of ground-glass (with stars), rushing upstairs. I told Mr. Franching to wait at the door while I went round to the side. There I saw the grocer’s boy actually picking off the paint on the door, which had formed into blisters. No time to reprove him; so went round and effected an entrance through the kitchen window. I let in Mr. Franching, and showed him into the drawing-room. I went upstairs to Carrie, who was changing her dress, and told her I had persuaded Mr. Franching to come home. She replied: “How can you do such a thing? You know it’s Sarah’s holiday, and there’s not a thing in the house, the cold mutton having turned with the hot weather.”\n\nEventually Carrie, like a good creature as she is, slipped down, washed up the teacups, and laid the cloth, and I gave Franching our views of Japan to look at while I ran round to the butcher’s to get three chops.\n','\n',char(10)),'http://www.gutenberg.org/files/1026/1026-h/1026-h.htm',replace('26 Jun 2020\n','\n',char(10)),'3',replace('QUESTION\n\nWhy did the author buy three chops?\n\n\nANSWER\n\nBecause there were three people.\n\n','\n',char(10))); +INSERT INTO article VALUES(16,replace('Why Everyone Should Use a Paper Planner\n\nOkay, so maybe not exactly everyone should use a paper planner. If you are one of those people who loves your Google calendar and phone alerts then maybe paper isn''t for you. Maybe I''m just tired of all the people that tell me paper planners are obsolete and I should definitely go digital, because I''m here to tell you that digital is not where it is at for me in calendars and planners.\n\nI would never show up anywhere. Believe me, I''ve tried the digital thing. Google calendar and me are not friends. At work, I try to use it, sort of. At least, I get alerts to go teach my class (set up by the department secretary), and my students will sometimes send me their calendars for scheduling. But mine hasn''t been updated for several years.\n','\n',char(10)),'https://www.overstuffedlife.com/2015/02/why-everyone-should-use-paper-planner.html','12 Jul 2020','2',replace('QUESTION\n\nWhich type of calendar does the author prefer, digital or paper?\n\nANSWER\n\nPaper.\n','\n',char(10))); +INSERT INTO article VALUES(17,replace('Why Writing Works Better Than Typing\n\nMelanie Pinola\n\nThere may also be a scientific basis for the pen’s superiority over the keyboard when it comes to writing development and cognitive functions. Dr. Virginia Berniger, who studies reading and writing systems and their relationship to learning processes, found that children’s writing ability was consistently better (they wrote more, faster, and more complete sentences) when they used a pen rather than a keyboard; these are, of course, subjects without a penchant for using either tool. We also previously covered the WSJ article that connected handwriting and cognitive abilities; in one of the studies cited, adults learned new symbols and graphic shapes better when they reproduced them with pen-and-paper instead of typing them.\n\nThe difference, Berniger notes, may lie in the fact that with writing, you use your hand to form the letters (and connect them), thereby more actively engaging the brain in the process. Typing, on the other hand, involves just selecting letters by pressing identical-looking keys.\n\nOf course, whether the pen or the keyboard is better for you depends on your personal experience and comfort with these tools. As a compromise, perhaps we should all get stylus-friendly tablet PCs or digital pens.\n','\n',char(10)),'https://lifehacker.com/why-you-learn-more-effectively-by-writing-than-by-typin-5738093','12 Jul 2020','3',replace('QUESTION\n\nPen always works better than keyboard in terms of writing ability development. Is this statement true or false?\n\nANSWER\n\nFalse.\n','\n',char(10))); +INSERT INTO article VALUES(18,replace('Can the Internet save us from epidemics?\n\n\n\nDavid M. Eagleman \n\nNature\n\nPublished: 31 May 2006\n\n\nSir\n\n\nKathleen Morrison, in News & Views (“Failure and how to avoid it” Nature 440, 752–754; 2006), notes that societies have often prevented collapse by adopting new technological strategies. In today''s world, where one of the most-talked about prospects for collapse is an epidemic of infectious disease, it is worth remembering that perhaps we already have the technological strategy to avoid it — the Internet.\n\nRemote working, made possible by the Internet (‘telepresence’), is already a key component of national and business pandemic plans. Telepresence can inhibit viral transmission by reducing human-to-human contact. Prepared organizations can leverage telepresence to allow continued productivity and functioning of supply chains during an outbreak.\n\nPast societies often reacted to epidemics by bunching together, increasing density and transmission rates. In medieval Europe, for example, warring religious factions demonstrated solidarity in the face of a plague by marching together in the streets. And Native Americans expressed goodwill by gathering in the teepees of those infected with smallpox. But if we are well-prepared when an epidemic arrives, we can fluidly shift into a self-quarantined, telepresent society in which microbes fail by dint of host sparseness.\n\nWhatever the social ills of increased isolation in our computer age, they may bode worse for the microbes than for us.\n\n','\n',char(10)),'https://doi.org/10.1038/441574c','13 Jul 2020','3',replace('QUESTION\n\nWhat is the tool mentioned by the author for avoiding society collpase due to epidemic?\n\nANSWER\n\nThe Internet.\n','\n',char(10))); +INSERT INTO article VALUES(19,replace('Space-age style by the sea -- Rugen Island Germany\n\nFeatured on Bing\n\nAugust 6, 2020\n\n\nThis pod-like structure near the seaside resort of Binz, on the Pomeranian coast of northeast Germany, provides a snapshot into a different era, delivered by the architect Ulrich Müther. Originally a lifeguard tower, it was constructed in 1968 in a style known as shell architecture using an innovative thin, poured-concrete material. Müther designed and built roughly 70 buildings in this manner, many of them here on the island of Rügen, where he lived. His work is regarded as some of the most outstanding examples of architecture in the region.\n\n','\n',char(10)),'https://cn.bing.com/search?q=rugen+island+germany&form=HPVSBS&filters=HpDate%3a%2220200806_0700%22','12 Aug 2020','3',replace('QUESTION\n\nWho is the architect of the pod-like structure on the Pomeranian coast in Germany?\n\nANSWER\n\nUlrich Müther.\n','\n',char(10))); +INSERT INTO article VALUES(20,replace('Interview: China "locomotive" for post-pandemic global recovery, says economist\n\nGENEVA, Aug. 12 (Xinhua) -- China is expected to play the role of a "locomotive" for powering global recovery in the post-pandemic era, a Swiss economist has said.\n\n"The Chinese market has become an important growth driver because of its size and its continuing expansion," Rudolf Minsch, chief economist at Swiss national business federation Economiesuisse, told Xinhua in a recent interview.\n\nMoreover, it is "absolutely crucial that China is opposing any tendency to reverse globalization," Minsch said, adding China has been keeping up the effort to "establish a market-oriented, law-based and internationalized business environment."\n\n"The most important part of Chinese economic policy today, in my view, is the commitment of the government to widening the door to the world, despite the difficulty arising from the coronavirus crisis," Minsch said.\n\n"Open markets are key to the long-term growth of China and are so to the rest of the world," he added.\n\nThis year marks the 70th anniversary of the diplomatic relations between Switzerland and China. Since 2010, China has been Switzerland''s biggest trading partner in Asia and its third largest globally after the European Union and the United States. A free trade agreement between the two countries was signed in 2013 and entered into force on July 1, 2014.\n\n"There are so many Swiss companies in China, collaborating with Chinese firms as customers, as suppliers or as research and development partners," Minsch noted.\n\nWhile those companies face "tough competition" in the Chinese market, they also have huge opportunities "to benefit from the very efficient and speedy way of Chinese enterprises to develop new products and services," he said.\n\n"In most cases, the products and services of the two countries are complementary. In parallel with the higher income of the Chinese population, the demand for Swiss products and services will rise," he added.','\n',char(10)),'http://www.xinhuanet.com/english/2020-08/13/c_139287340.htm','13 Aug 2020','3',replace('QUESTION\n\nIn which year was the free trade agreement between China and Switzerland signed?\n\nANSWER\n\n2013.','\n',char(10))); +INSERT INTO article VALUES(21,replace('Introducing DigitalOcean''s Engineering Code of Conduct\n\nA code of conduct is designed to be a framework and a guide to, as the Recurse Center eloquently phrased it, "help all of us build a pleasant, productive, and fearless community." The purpose of a code of conduct is not to burden an organization with a bunch of needless rules, or to provide a punishment mechanism for people being bad, or even to correct things that have been wrong in the past. The engineering team at DigitalOcean agreed that having a code of conduct would be a positive improvement because we strive to make our team a great group of people to work with, especially for those people who have faced more adverse working environments in the past or are member of groups that often have a harder time in the workplace.\n','\n',char(10)),'https://github.com/digitalocean/engineering-code-of-conduct/blob/master/introduction.md','14 Aug 2020','3',replace('QUESTION\n\nThe main purpose of having a code of conduct is to punish people who violated it. Is this statement true of false?\n\nANSWER\n\nFalse.','\n',char(10))); +INSERT INTO article VALUES(22,replace('Politicizing Confucius Institute program detrimental to long-term China-U.S. ties\n\nBEIJING, Aug. 14 (Xinhua) -- The U.S. administration''s requirement of the Confucius Institute U.S. Center to register as a foreign mission is nothing short of sheer politicization of educational exchanges between the two countries.\n\nThe move came after some Chinese media organizations in the United States had been designated as foreign missions earlier. Driven by a Cold-War mentality, such a detrimental step will further undermine the mutual trust and cooperation between China and the United States.\n\nInaugurated in 2013, the Confucius Institute U.S. Center is a nonprofit educational institution that supports the teaching and learning of Chinese language and culture in the United States for deeper cross-cultural understanding and language development.\n\nAll Confucius Institutes in the United States are based on voluntary participation by U.S. universities and jointly established in accordance with the principles of mutual respect, friendly consultation, equality and mutual benefit of Chinese and U.S. universities. The daily operation and management of these Confucius Institutes observe local laws and are transparent.\n\nIn disregard of the organization''s role in promoting mutual understanding between the two peoples, the U.S. administration has demonized and stigmatized the normal functioning of the Confucius Institute program and has been attempting to create an atmosphere of fear in the field of educational exchanges, only to serve U.S. strategic agenda of containing China.\n\nThe U.S. administration has ramped up its attack on Chinese high-tech companies and trade businesses, and now it is stoking ideological confrontation in the educational and cultural sector, another perilous move to decouple the two countries.\n\nNarrowing the opportunities for cultural understanding and mutual learning between the two peoples will lead to the destruction of long-term bilateral relations.\n\nSuch hysteria is a warning sign that calls for caution, as selfish and narrow-minded politicians are stealing the future of the China-U.S. relationship.\n','\n',char(10)),'http://www.xinhuanet.com/english/2020-08/14/c_139290711.htm','15 Aug 2020','4',replace('QUESTION\n\nConfucius Institutes are established in China universities.\nIs this statement true?\n\nANSWER\n\nNo. It is false. They are established in the US universities.','\n',char(10))); +INSERT INTO article VALUES(23,replace('Don''t be afraid of mistakes and false starts. They are part of the learning and assimilation experience.\n\n','\n',char(10)),'Boehm, B. W. (1983). Seven basic principles of software engineering. Journal of Systems and Software, 3(1), 3–24.','15 Aug 2020','3',replace('QUESTION\n\nChoose a word that is closest in meaning to assimilation.\n\nA. Forgetting\nB. Digesting\nC. Understanding\nD. Killing\n\n\nANSWER\n\nC.','\n',char(10))); +INSERT INTO article VALUES(24,replace('DELETE YOUR SH!T: WHY YOU SHOULD TRASH MOST OF YOUR PHOTOS\n\n\nApril 21, 2016 by JP Danko\n\n\nLets start with a universal truth.\n\n99% of the photos that I take, that you take or that any other\nphotographer takes are junk that nobody will ever see, or ever want to see.\n\nSo in this article I am going to encourage you to trash everything except your best work – after hitting delete you’ll feel better, I promise.\n\nThere are obviously many reasons to save your photography and I am sure that the “save everything forever” camp will explain everything in the comments.\n\nHowever, be honest with yourself – most of the reasons for permanently archiving every photo that comes off of our camera(s) are just little white lies we like to tell ourselves.\n\nFor example:\n\n“I might want to re-process this shoot another way in the future.”\n\n“Storage is cheap so its actually easier to keep everything.”\n\n“I will re-process this timelapse to 4k once I get a better computer.”\n\n“I like all of the 299 photos I took of my kid blowing out their birthday candles on continuous high speed.”\n\n“I’m only going to do a quick edit now, I’ll fix the rest later.”\n\n“I only created one HDR from this series of 10,000 photos I took of the same thing – I will process the rest later.”\n\n“Clients actually prefer to receive 5000 images.”\n\n“I can’t fix this photo yet – but the software of the future will be able to do it.”\n\n“I don’t like it now, but I might like it better in a few years.”\n\n“I need 1000 photos to tell the story.”\n\nLies, each and every one!\n\n','\n',char(10)),'https://www.diyphotography.net/delete-sht-trash-photos/','16 Aug 2020','3',replace('QUESTION\n\nThe author believes that 99% of photos he has taken are shit and should be deleted. Is this statement true?\n\n\nANSWER\n\nTrue.','\n',char(10))); +INSERT INTO article VALUES(25,replace('Definition of Success\n\nThe Japanese value project team success far more than individual accomplishment. Thus programmers honestly report the bugs they produced during all phases of software development. Such defect data serves to create and validate software quality assurance theories, which are intrinsically statics-based and empirical.\n\nOn the other hand, US culture values personal achievement over team success. Since reporting "I caused this many bugs" automatically implies "I am this stupid", a programmer will likely fudge his bug statistics when submitting them to a manager. Needless to say, this makes the application of QA theory difficult, and virtually guarantees that US companies will produce flawed software.','\n',char(10)),'Yamaura, Tsuneo. (1998). Why Johnny Can''t Test. IEEE Computer Society Press.','18 Aug 2020','4',replace('QUESTION\n\nIn which country do programmers tend to underreport their bugs?\n\n\nANSWER\n\nThe US.','\n',char(10))); +INSERT INTO article VALUES(26,replace('Human Characteristics\n\nAccording to Shepard, a person''s characteristics can span two or more types. He called someone both A and P characteristics the Genius type because that person can come up with a great idea and be persistent enough to prove it loigcally. Einstein epitomizes this A-P type. A type C-F person is a born manager who knows how to effectively use carrots and sticks.\n\n','\n',char(10)),'Yamaura, Tsuneo. (1998). Why Johnny Can''t Test. IEEE Computer Society Press.','18 Aug 2020','3',replace('QUESTION\n\nA person can have only one characteristic.\nIs this statement true?\n\n\nANSWER\n\nFalse.','\n',char(10))); +INSERT INTO article VALUES(27,replace('Coca-Cola continues to expand investment in China supply chain\n\nSource: Xinhua| 2020-08-17 22:11:14\n\nSHANGHAI, Aug. 17 (Xinhua) -- Coca-Cola China and its bottling partners will continue to expand investment in local supply chains to improve efficiency, ensure supply, and serve domestic consumers'' demand.\n\nThe beverage giant achieved good second-quarter results in the Chinese market, despite the impact of the COVID-19 epidemic, and continues to set up new factories and production lines in China to meet evolving consumer needs.\n\nIn the second half of 2020, Swire Coca-Cola, a bottler of Coca-Cola, plans to put six new production lines into operation, with a total investment of 250 million yuan (about 36 million U.S. dollars) and an additional annual output value exceeding 1.7 billion yuan.\n\nSwire Coca-Cola also plans to add a plastic bottle production line to its plant in central China''s Hubei Province, which is expected to go operational in May 2021.','\n',char(10)),'http://www.xinhuanet.com/english/2020-08/17/c_139297443.htm','18 Aug 2020','3',replace('QUESTION\n\nName a bottling partner of Coca-Cola China.\n\n\nANSWER\n\nSwire Coca-Cola.','\n',char(10))); +INSERT INTO article VALUES(28,replace('What Makes A Great Software Engineer?\n\nGood software engineers are essential to the creation of good software. However, most of what we know about software-engineering expertise are vague stereotypes, such as ‘excellent communicators’ and ‘great teammates’. The lack of specificity in our understanding hinders researchers from reasoning about them, employers from identifying them, and young engineers from becoming them. Our understanding also lacks breadth: what are all the distinguishing attributes of great engineers (technical\nexpertise and beyond)? We took a first step in addressing these gaps by interviewing 59 experienced engineers across 13 divisions at Microsoft, uncovering 53 attributes of great engineers. We explain the attributes and examine how the most salient of these impact projects and teams. We discuss implications of this knowledge on research and the hiring and training of engineers.','\n',char(10)),replace('Li, P. L., Ko, A. J., & Zhu, J. (2015). What makes a great software engineer. In 2015 IEEE/ACM 37th IEEE International Conference on Software Engineering (Vol. 1, pp. 700–710).\n\nhttps://faculty.washington.edu/ajko/papers/Li2015GreatEngineers.pdf','\n',char(10)),'20 Aug 2020','3',replace('QUESTION\n\nHow did the authors get the distinguishing attributes of great engineers at Microsoft?\n\n\nANSWER\n\nBy interviewing.','\n',char(10))); +INSERT INTO article VALUES(29,replace('Number One Reason Why Projects Fail\n\nBy Neal Whitten\n\nThis is a good time to share with you what I believe may be a profound\nassertion. We have all seen lists touting the top 10 reasons why\nprojects fail. The usual suspects include weak requirements, scope\ncreep, lack of user involvement, unreliable estimates, incomplete\nstaffing, poor communications, weak senior stakeholder support and\nothers. However, from my experience, these lists miss the biggest\nreason — the number one reason — why projects fail: Because the\nproject manager does not manage to his or her top three priorities on\na daily basis.\n\nThis is so important that I’m going to repeat it. The number one\nreason why projects fail is that the project manager does not manage\nto his or her top three priorities on a daily basis. You might be\nwondering how come I’m so smart to get this while it appears that\nothers haven’t? Well, I’m not that smart, but I am an old guy who has\nbeen around a long time. Longevity and persistence helps me pick up\nthings. For example, over the years I have performed reviews on\nhundreds of projects in trouble. When I do, I always conclude with\nidentifying the top three problems — the top three priorities — that\nthe project manager needs to address immediately. When I examine\nthese top three lists, the ah-ha moment presents itself. The top\nitems on the lists almost always should have been resolved not days\nearlier but weeks or months earlier — sometimes years depending on the\nduration of the project.\n\nThe lists show that the project managers were not effectively focusing\non their top three priorities on a daily basis; otherwise, these\nproblems would have been resolved or under control. So, again, the\nnumber one reason why projects fail is that the project manager does\nnot manage to his or her top three priorities on a daily basis. This\nis a fundamental fact that knowing and adjusting your behavior to can\nsignificantly increase the success of your projects — and your career.\nBy the way, the article might have appeared to focus on Project\nManagers, not Business Analysts. Everything said here also applies to\nBusiness Analysts.\n\nThe number one reason why Business Analysts fail is that the Business\nAnalyst does not manage to his or her top three priorities on a daily\nbasis. ','\n',char(10)),'https://nealwhittengroup.com/wp-content/uploads/2017/12/You-Desire-Success.pdf','23 Aug 2020','3',replace('QUESTION\n\nWhat is the number one reason that project fail, according to the author?\n\n\nANSWER\n\nThe project manager does not manage to his top three priorities on a daily basis.','\n',char(10))); +INSERT INTO article VALUES(30,replace('Overboard\n\nA few years ago the movie “Overboard” was released. This is a movie about a rich woman (JoAnna) who was accustomed to having everything her own way. The movie begins with JoAnna hiring an uncouth carpenter (Dean) to remodel the closet of her luxurious yacht. Following several unpleasant encounters between the two during the remodeling project, a major confrontation occurs as the carpenter has completed work, and the yacht is preparing to leave port.\n\nWhile the carpenter is demonstrating the features of his work, the rich, arrogant, JoAnna asks what the closet is made of. In response, Dean indicates that the closet is made of oak. His response pushes JoAnna over the edge. She says that she wanted the closet to be made of cedar. The carpenter responds that if she wanted the closet to be made out of cedar, she should have asked for cedar. He tells her that he would be glad to make the closet out of cedar, but that his estimate would be more than double because he would have to redo the whole project. To which she responded, “the whole civilized world knows that closets are made of cedar!” She further indicates that she is not going to pay for “his” mistake! The confrontation escalates to the point that she pushes Dean overboard. ','\n',char(10)),'Leishman and Cook. "Requirements Risks Can Drown Software Projects." Computer (November 2001). ','24 Aug 2020','4',replace('QUESTION\n\nWhat material does JoAnna want for her closet?\n\n\nANSWER\n\nCedar.','\n',char(10))); +INSERT INTO article VALUES(31,replace('Chiding Children\n\n\nAs children should very seldom be corrected by blows; so, I think, frequent, and especially, passionate chiding, of almost as ill consequence. It lessons the authority of the parents, and the respect of the child: for I bid you still remember, they distinguish early betwixt passion and reason: and as they cannot but have a reverence for what comes from the latter, so they quickly grow into a contempt of the former; or if it causes a present terrour, yet it soon wears off; and natural inclination will easily learn to slight such scare-crows, which make a noise, but are not animated by reason. Children being to be restrained by the parents only in vicious (which, in their tender years, are only a few) things, a look or nod only ought to correct them, when they do amiss: or, if words are sometimes to be used, they ought to be grave, kind, and sober, representing the ill, or unbecomingness of the faults, rather than a hasty rating of the child for it, which makes him not sufficiently distinguish whether your dislike be not more directed to him than his fault. Passionate chiding usually carries rough and ill language with it, which has this further ill effect, that it teaches and justifies it in children; and the names that their parents or preceptors give them they will not be ashamed or backward to bestow on others, having so good authority for the use of them.','\n',char(10)),'The Works of John Locke in Nine Volumes, (London: Rivington, 1824 12th ed.). Vol. 8. The Online Library of Liberty.','25 Aug 2020','4',replace('QUESTION\n\nChildren cannot tell the difference between passion and reason. Is this statement true?\n\n\nANSWER\n\nFalse.','\n',char(10))); +INSERT INTO article VALUES(32,replace('Apple Threatens to Terminate Epic Games'' Developer Accounts on August 28\n\nMonday August 17, 2020 12:02 pm PDT by Juli Clover\n\nApple is planning to terminate Epic Games'' entire access to its App Store and app development tools, Epic Games said today. Apple told Epic that by August 28, all access will be ended.\n\nThat includes Epic''s access to the development tools necessary to create software for the Unreal Engine that Epic offers to third-party developers for their games. In response, Epic has filed a court order asking a Northern California court to stop Apple from removing Epic''s ‌App Store‌ access. \n\nFrom the filing:"\nIt told Epic that by August 28, Apple will cut off Epic''s access to all development tools necessary to create software for Apple''s platforms--including for the Unreal Engine Epic offers to third-party developers, which Apple has never claimed violated any Apple policy."\n\nCutting off Epic''s access to Mac and iOS developer tools could have a significant impact on all of the apps and games that use Epic''s Unreal Engine. Apple in its letter to Epic Games letting it know about the upcoming account closures says that Epic can avoid having its access revoked by following Apple''s ‌App Store‌ guidelines.\n\n','\n',char(10)),'https://www.macrumors.com/2020/08/17/apple-terminate-epic-developer-accounts-august-28/',replace('25 August 2020\n','\n',char(10)),'4',replace('QUESTION\n\nWhich company sued which company in the Northern California court?\n\n\nANSWER\n\nEpic Games sued Apple.','\n',char(10))); +INSERT INTO article VALUES(33,'“Sometimes ... that’s just arduous. You really just need to grind through.” - Software Development Engineer Level 2, Server & Tools','Li, P. L., Ko, A. J., & Zhu, J. (2015). What makes a great software engineer. In 2015 IEEE/ACM 37th IEEE International Conference on Software Engineering (Vol. 1, pp. 700–710).','26 August 2020','4',replace('QUESTION\n\nWhich one of the following words best describes the content of the above passage?\n\nA. Passionate\n\nB. Systamic\n\nC. Curious\n\nD. Hardworking\n\nANSWER\n\nD.','\n',char(10))); +INSERT INTO article VALUES(34,replace('Section 80 -- Some Thoughts Concerning Education\n\nBut since the occasions of punishment, especially beating, are as much to be avoided as may be, I think it should not be often brought to this point. If the awe I spoke of be once got, a look will be sufficient in most cases. Nor indeed should the same carriage, seriousness, or application be expected from young children, as from those of riper growth. They must be permitted, as I said, the foolish and childish actions, suitable to their years, without taking notice of them; inadvertency, carelessness, and gaiety, is the character of that age. I think the severity I spoke of, is not to extend itself to such unseasonable restraints; nor is that hastily to be interpreted obstinacy or wilfulness, which is the natural product of their age or temper. In such miscarriages they are to be assisted, and helped towards an amendment, as weak people under a natural infirmity; which, though they are warned of, yet every relapse must not be counted a perfect neglect, and they presently treated as obstinate. Faults of frailty, as they should never be neglected, or let pass without minding; so, unless the will mix with them, they should never be exaggerated, or very sharply reproved; but with a gentle hand set right, as time and age permit. By this means, children will come to see what is in any miscarriage, that is chiefly offensive, and so learn to avoid it. This will encourage them to keep their wills right, [69] which is the great business; when they find, that it preserves them from any great displeasure; and that in all their other failings they meet with the kind concern and help, rather than the anger and passionate reproaches of their tutor and parents.','\n',char(10)),'https://oll.libertyfund.org/titles/locke-the-works-vol-8-some-thoughts-concerning-education-posthumous-works-familiar-letters','28 Aug 2020','4',replace('QUESTION\n\nParents must beat children for their foolish and childish actions. Is this statement true?\n\n\nANSWER\n\nFalse.','\n',char(10))); +INSERT INTO article VALUES(35,replace('Section 81 -- Some Thoughts Concerning Education\n\n\nIt will perhaps be wondered, that I mention reasoning with children: and yet I cannot but think that the true way of dealing with them. They understand it as early as they do language; and, if I mis-observe not, they love to be treated as rational creatures, sooner than is imagined. It is a pride should be cherished in them, and, as much as can be, made the greatest instrument to turn them by.','\n',char(10)),'https://oll.libertyfund.org/titles/locke-the-works-vol-8-some-thoughts-concerning-education-posthumous-works-familiar-letters','29 Aug 2020','4',replace('QUESTION\n\nChildren do not like to be treated as rational creatures.\nIs this statement true?\n\n\nANSWER\n\nFalse.','\n',char(10))); +INSERT INTO article VALUES(36,replace('Another China fab project stalled\n\nBy David Manners\n\n28th August 2020\n\n\nWuhan Hongxin Semiconductor Manufacturing Company (HSMC) has been building a $20 billion semiconductor production site in Dongxihu for two years but the local government has said that construction has been halted because the money has run out.\n\nHSMC intended to build a 14 nanometer logic processor production line with a capacity of 30000 wpm and a 7nm logic process production line with a capacity of 30000 pieces per month and a wafer level advanced packaging production line.\n\nThe halt in construction at HSMC follows abandoned fab plans at the jv between Globalfoundries and the City of Chengdu, the discontinued DRAM fab site of Fujian JinHua and the bankruptcy of Tacoma Nanjing Semiconductor Technology which was building a $3 billion fab backed by the government.\n\n\nThere are reports of HSMC’s contractors not being paid including one from clean-room specialist L&K Engineering which said in its half year report that it had stopped work because of delayed payments.\n\n When asked for a comment on the situation by the South China Morning Post, HSMC’s chairman Chiang Shang-yi – formerly of TSMC and SMIC – said he was not aware of the company’s financial problems.\n\nDr Chiang was head of R&D at TSMC.','\n',char(10)),'https://www.electronicsweekly.com/news/business/another-china-fab-project-stalled-2020-08/','29 Aug 2020','4',replace('QUESTION\n\nWhere is the location of HSMC?\n\n\nANSWER\n\nDongxihu.','\n',char(10))); +INSERT INTO article VALUES(37,replace('How you work is as important as what you work on\n\nThe tools you choose matter. Tools are more than mere convenience. Tools force teams into particular workflows, workflows that constrain not just how software is produced, but what software is possible. It’s no coincidence then that the open source community, in order to produce the type of software it produces, adopts vastly different tools than most enterprise developers have available to them at their office.','\n',char(10)),'Source: https://ben.balter.com/2020/08/14/tools-of-the-trade/','30 Aug 2020','3',replace('QUESTION\n\nWhich developers use more tools, open source developers or enterprise developers?\n\n\nANSWER\n\nOpen source developers.','\n',char(10))); +INSERT INTO article VALUES(38,replace('Things go tougher for Huawei\n\nAP | Aug 20, 2020, 05:19PM\n\nNow, Huawei Technologies Ltd. is suffering in earnest as Washington intensifies a campaign to slam the door on access to foreign markets and components in its escalating feud with Beijing over technology and security.\n\nEuropean and other phone carriers that bought Huawei gear despite U.S. pressure are removing it from their networks. Huawei got a flicker of good news when it passed rivals Samsung and Apple as the No. 1 smartphone brand in the quarter ending in June thanks to sales in China, but demand abroad is plunging.\n\n``Huawei is losing market share quite dramatically outside China,'''' said industry analyst Paul Budde. ``Their international position is most likely going to get worse rather than better.''''\n\nIn the latest blow, the Commerce Department this week confirmed rules announced in May that will bar non-American companies from using U.S. technology to make processor chips and other components for Huawei without a government license.\n\nThe president of Huawei''s consumer business, Richard Yu, says it is running out of chips for smartphones. Yu said as of Sept. 15, contractors will be forced to stop making Kirin chips designed by Huawei''s engineers and used in its most advanced handsets.\n\n``This is a very big loss for us,'''' Yu said Aug. 8 at an industry conference, China Info 100.\n','\n',char(10)),'Source: https://www.gadgetsnow.com/tech-news/things-go-tougher-for-huawei/articleshow/77654934.cms','31 Aug 2020','3',replace('QUESTION\n\nWhy is Huawei losing its market share outside China?\n\n\nANSWER\n\nU.S. sanctions.','\n',char(10))); +INSERT INTO article VALUES(39,replace('Beating\n\n\nJohn Locke\n\nbeating is the worst, and therefore the last, means to be used in the correction of children; and that only in cases of extremity, after all gentler ways have been tried, and proved unsuccessful: which, if well observed, there will be very seldom any need of blows. For, it not being to be imagined that a child will often, if ever, dispute his father’s present command in any particular instance; and the father not interposing his absolute authority, in peremptory rules, concerning either childish or indifferent actions, wherein his son is to have his liberty; or concerning his learning or improvement, wherein there is no compulsion to be used; there remains only the prohibition of some vicious actions, wherein a child is capable of obstinacy, and consequently can deserve beating: and so there will be but very few occasions of that discipline to be used by any one, who considers well, and orders his child’s education as it should be. \n\nFor the first seven years, what vices can a child be guilty of, but lying, or some ill-natured tricks; the repeated commission whereof, after his father’s direct command against it, shall bring him into the condemnation of obstinacy, and the chastisement of the rod? If any vicious inclination in him be, in the first appearance and instances of it, treated as it should be, first, with your wonder; and then, if returning again a second time, discountenanced with the severe brow of the father, tutor, and all about him, and a treatment suitable to the state of discredit before mentioned; and this continued till he be made sensible and ashamed of his fault; I imagine there will be no need of any other correction, nor ever any occasion to come to blows. \n\nThe necessity of such chastisement is usually the consequence only of former indulgences or neglects. If vicious inclinations were watched from the beginning, and the first irregularities which they caused, corrected by those gentler ways, we should seldom have to do with more than one disorder at once; which would be easily set right without any stir or noise, and not require so harsh a discipline as beating. Thus, one by one, as they appeared, they might all be weeded out, without any signs or memory that ever they had been there. But we letting their faults (by indulging and humouring our little ones) grow up, till they are sturdy and numerous, and the deformity of them makes us ashamed and uneasy; we are fain to come to the plough and the harrow; the spade and the pick-ax must go deep to come at the roots, and all the force, skill, and diligence we can use, is scarce enough to cleanse the vitiated seed-plat, overgrown with weeds, and restore us the hopes of fruits to reward our pains in its season.','\n',char(10)),'Source: https://oll.libertyfund.org/titles/locke-the-works-vol-8-some-thoughts-concerning-education-posthumous-works-familiar-letters','2 Sep 2020','4',replace('QUESTION\n\nBeating is the most effective method of correcting children.\nIs this statement true?\n\n\nANSWER\n\nFalse.','\n',char(10))); +INSERT INTO article VALUES(40,replace('Tutor\n\nIf a tutor can be got, that, thinking himself in his father’s place, charged with his care, and relishing these things, will at the beginning apply himself to put them in practice, he will afterwards find his work very easy: and you will, I guess, have your son in a little time a greater proficient in both learning and breeding, than perhaps you imagine. But let him by no means beat him, at any time, without your consent and direction: at least till you have experience of his discretion and temper. But yet, to keep up his authority with his pupil, besides concealing that he has not the power of the rod, you must be sure to use him with great respect yourself, and cause all your family to do so too. For you cannot expect your son should have any regard for one, whom he sees you, or his mother, or others slight. If you think him worthy of contempt, you have chosen amiss; and if you show any contempt of him, he will hardly escape it from your son: and whenever that happens, whatever worth he may have in himself, and abilities for this employment, they are all lost to your child, and can afterwards never be made useful to him.','\n',char(10)),'Source: https://oll.libertyfund.org/titles/locke-the-works-vol-8-some-thoughts-concerning-education-posthumous-works-familiar-letters','6 Sep 2020','3',replace('QUESTION\n\nTo establish a tutor''s authority while educating a child, only the father in the family needs to show great respect to the tutor. Is this statement true?\n\n\nANSWER\n\nFalse.','\n',char(10))); +INSERT INTO article VALUES(41,replace('Oxbotica’s pioneering deepfake technology brings Universal Autonomy within sight\n\n25th June 2020\n\n\nOxbotica has developed and deployed a “deepfake” technology that is capable of generating thousands of photo-realistic images in minutes; helping to expose its autonomous vehicles to the near infinite variations of the same situation – without real-world testing of a location having ever taken place.\n\nDeepfaking, which first shot to fame when it was used to create viral internet videos, employs deep learning artificial intelligence (AI) to generate fake photo-realistic images.\n\nThe AV software firm believes that the pioneering technology will make the vehicles of tomorrow smarter and safer, and immediately accelerate the race to autonomy.\n\nSophisticated deepfake algorithms allow the autonomous vehicle software firm to reproduce the same scene in poor weather or adverse conditions, and subject its vehicles to rare occurrences.\n\nThe technology is so advanced that it can reverse road signage or “class switch”, where one object (e.g. a tree) is replaced with another (e.g. a building). It can change the lighting of an image, to show a particular frame at a different time of the day or season of the year, all while ensuring shadows or reflections appear exactly as they should. It then uses these synthetic images to teach its software, producing thousands of accurately-labelled, true-to-life experiences and rehearsals which are not real but generated; even down to the rain drops on lenses.\n\n','\n',char(10)),'Source: https://www.oxbotica.com/insight/oxboticas-pioneering-deepfake-technology-brings-universal-autonomy-within-sight/','14 Sep 2020','4',replace('QUESTION\n\nDeepfake images are not original images. They are computer generated. Is this statement true?\n\n\nANSWER\n\nTrue.','\n',char(10))); +INSERT INTO article VALUES(42,replace('DRIVEN project demonstrates how driverless cars can operate safely in London\n\n\nThe DRIVEN consortium celebrates today a key milestone in this 30-month government-supported project by unveiling the capabilities of a fleet of self-driving vehicles in London’s challenging and complex urban environment.\nPublished on 30 September 2019','\n',char(10)),'Source: https://trl.co.uk/news/news/driven-project-demonstrates-how-driverless-cars-can-operate-safely-london','15 Sep 2020','3',replace('QUESTION\n\nIn which city did the driverless car operate?\n\n\nANSWER\n\nLondon.','\n',char(10))); +INSERT INTO article VALUES(43,replace('How to Learn to Program\n\nOctober 9, 2018\n\n\nOne question that people ask me all the time is, “How do I become a programmer?” Or, “How do I learn to program?” There are a lot of possible answers to this, depending on the person and how you want to go about it. I figured that since people ask me this so often, I had better finally write an article about it.\n\n\nUniversity\nThe most commonly-taught subject that’s related to programming in universities is called “computer science.” I say that it’s related to programming because very little of what people learn in most computer science courses will actually end up being useful in their day-to-day lives as a professional, working programmer. That’s not always true—there are some fields where computer science comes very much in handy. But in general, the field we call “software engineering” or “development” is different than what universities cover as “computer science.”\n\nUsually, the basics of computer science that universities cover are very useful. I went to university and studied computer science, and my first two years of study were very useful to me, especially the first few classes. I got a great grounding in some of the basic concepts of software development.\n\nWhat I didn’t realize at the time, though, is that computer science is only partly a study of programming. The other part is a study of algorithms. (For those who are reading this and don’t know, an algorithm is a series of steps for accomplishing some task. That’s really all it means. Even a shopping list is a sort of algorithm.) The study of algorithms usually involves learning the most efficient way to do something. That is, figuring out how to accomplish a task like sorting a list of integers using the fewest number of steps or using the least amount of memory. There are some problems that can’t be solved by computers at all unless you know the right algorithm, and once in a while you run into a problem in programming that requires this knowledge. So it does have some use. But solving these problems of algorithms is not what you will be spending most of your time doing.\n\nEven for those universities that offer courses in “software engineering,” they are rarely a full experience of what the real world will be like. The reason is that most courses only take a few months at most, and make you collaborate with only a few people at best, on a codebase of a few thousand lines of code. In the real world, you will be working with a large number of people on a codebase that will last for years that is at least tens of thousands of lines of code. However, these software engineering courses are still far better than nothing.\n\nAll this said, there are a few universities that do turn out excellent programmers, whether that be by computer science courses or software engineering courses. And there is always some value in learning to program by taking classes at a university. At the very least, being at a university provides a structure and discipline that encourages you to get through the class.\n\n','\n',char(10)),'Source: https://www.codesimplicity.com/post/how-to-learn-to-program','5 Oct 2020','4',replace('QUESTION\n\nWhat is an algorithm?\n\n\nANSWER\n\nA series of steps for accomplishing some task.\n','\n',char(10))); +INSERT INTO article VALUES(44,replace('McConnell backs Trump legal fight in election results\n\n10 November 2020\n\nSenate Majority Leader Mitch McConnell backed the Trump campaign’s legal challenge of voting results in several battleground states on Monday in his first public comments on the floor since Election Day.\n\nIn his remarks, McConnell, R-Ky., said, “no states have yet certified their election results” and that recounts are already expected to occur in “at least one or two states.” The longtime senator argued that President Trump is “100 percent within his rights to look into allegations of irregularities and weigh his legal options.”\n\nMeanwhile, Attorney General William Barr on Monday gave federal prosecutors the green light to pursue "substantial allegations" of voting irregularities before the 2020 presidential election is certified next month, even though little evidence of fraud has been put forth.','\n',char(10)),'Source: https://www.foxnews.com/politics/live-updates-mcconnell-backs-trump-legal-fight-in-election-results','20 Nov 2020','4',replace('QUESTION\n\nThe election results are official at the time of writing this news. Is this statement true?\n\n\nANSWER\n\nFalse.\n','\n',char(10))); +INSERT INTO article VALUES(45,replace('Meet Minimum Requirements: Anything More is Too Much\n\nSeptember 1, 1998\n\nCommit to a project plan that only includes essential function, with a “closet plan” for nonessential function.\n\nby Neal Whitten, PMP, Contributing Editor\n\nDoes this conversation between a project manager and a project outsider sound familiar? It’s a Y2K project, but it could be any project.\n\nOutsider: “Will your project complete on time?”\nPM: “We have no choice.”\nOutsider: “I didn’t ask if you had a choice. I asked will you complete on time?”\nPM: “This is an important project. There’s a lot riding on the success of this project. We must complete on time.”\n\n(Translation: “No, we won’t complete on time. Anybody with any project experience knows this.”)\n\nIs this a Y2K-unique problem? No—it’s common on most projects. The primary reason it’s so common on Y2K projects is that most of the project managers and other project leaders on these projects were trained on pre-Y2K projects. Let me explain.\n\nOne of the most common problems with projects is taking on too much work—attempting to exceed requirements rather than meet minimum requirements. This contributes to a plethora of ill effects, including late deliveries, budget overruns, low morale and poor quality. Attempting to cram the proverbial 10 pounds into a 5-pound sack is a common occurrence.\n\nOne solution is to build products that meet minimum requirements. You may be thinking that such a product would have low appeal to your client or customers, but it’s not what you think.\n\n“Meet minimum requirements” means give the client what he or she needs to be successful; but don’t provide unessential function. Additional function is what future releases and future business opportunities are all about. It is important to earn the reputation for being reliable in meeting customer commitments and then be trusted to continue to upgrade on a routine, predictable basis. This is good business.\n\nYou say you always only provide essential function? For most of us, most times, that’s not true. Have you ever faced slipped delivery dates and chosen to remove some of the function originally planned? When the project began, everyone swore that all the planned function was essential. Yet, as the project progressed—and got further behind schedule—some of that essential function no longer looked so essential.\n\nWe’ll use a Y2K project as an example, because Y2K projects are at a heightened focus these days—and, interestingly enough, the No. 2 problem with Y2K projects is that they are taking on too much work (the No. 1 problem is that too many projects are starting too late). Here’s what should occur.\nLet’s say you’ve identified 100 functions (enhancements or changes) that need to be made in your company’s programs. You know that all 100 functions are desirable, but you recognize that your limited resources won’t allow all the functions to be ready by the hoped-for date. You find that 40 functions fall within the high-priority category, 30 as medium and 30 as low. You build a project plan to implement only the 40 high priorities. Why? Because you don’t want to jeopardize the timely completion of these 40 by building a plan to include the other 60 functions—all of lesser importance and, for purposes of illustration, deemed nonessential.\n\nYou might be thinking that you should build a plan with all 100 functions and later, if (actually, when) the project gets into trouble, you can always back out of lesser-priority function. Don’t go there! This foolish plan requires spending valuable time, dollars and resources working on other-than-the-most-important functions. Moreover, when you back out, it costs again. What needs to be done is to build a plan that significantly reduces rework. This means the original plan must be only essential function.\n\nWhat about the other 60? You carefully look these over and put work-arounds in place that, although not optimal, can get you through until more substantial actions can occur.\n\nBut there is something else you do. You decide on the most important of the 60 functions—maybe it’s all of the 30 medium functions or some subset thereof—and you create multiple, independent small projects with any and all resources you can muster. I call these small projects collectively a “closet plan.” These small projects are managed with the same care and attention to quality as the primary project. If any of these small projects can complete by a predetermined date (e.g., system test) and the risk to the primary project is judged to be acceptable, then the completed small projects are merged in with the primary project. There are many advantages to this technique: from reducing risk to the primary project, to motivating the members of the small projects to complete by a predetermined date, to setting customer expectations that are most likely to be met or exceeded.\n\nMost of us have been conditioned to believe that “meets minimum requirements” is unexciting and noncompetitive. I believe it to be the opposite. Deliberately practicing meeting minimum requirements helps an organization or company to be first-to-market, earn increasing credibility from their client(s), and strongly posture their enterprise for taking on new business opportunities. Adopting the concept of meeting minimum requirements can set your organization up for exceptional performance.','\n',char(10)),'Source: https://nealwhittengroup.com/articles/meet-minimum-requirements-anything-more-is-too-much/','20 Nov 2020','4',replace('QUESTION\n\nMeeting the minimum requirements is not exciting.\nIs this statement true?\n\nANSWER\n\nFalse\n','\n',char(10))); +INSERT INTO article VALUES(46,replace('Text of a statement from President Donald Trump on the election result\n\nNov 7, 2020 12:48 PM EST\n\n\n“We all know why Joe Biden is rushing to falsely pose as the winner, and why his media allies are trying so hard to help him: they don’t want the truth to be exposed. The simple fact is this election is far from over. Joe Biden has not been certified as the winner of any states, let alone any of the highly contested states headed for mandatory recounts, or states where our campaign has valid and legitimate legal challenges that could determine the ultimate victor. In Pennsylvania, for example, our legal observers were not permitted meaningful access to watch the counting process. Legal votes decide who is president, not the news media.\n\n“Beginning Monday, our campaign will start prosecuting our case in court to ensure election laws are fully upheld and the rightful winner is seated. The American People are entitled to an honest election: that means counting all legal ballots, and not counting any illegal ballots. This is the only way to ensure the public has full confidence in our election. It remains shocking that the Biden campaign refuses to agree with this basic principle and wants ballots counted even if they are fraudulent, manufactured, or cast by ineligible or deceased voters. Only a party engaged in wrongdoing would unlawfully keep observers out of the count room – and then fight in court to block their access.\n\n“So what is Biden hiding? I will not rest until the American People have the honest vote count they deserve and that Democracy demands.”\n\nThe statement was issued while Trump was golfing at his club in Virginia.','\n',char(10)),'Source: https://www.pbs.org/newshour/politics/read-president-donald-trumps-full-statement-on-the-election-results-vowing-to-head-to-the-courts','20 Nov 2020','4',replace('QUESTION\n\nWho wrote the above text?\n\nANSWER\n\nTrump.\n','\n',char(10))); +INSERT INTO article VALUES(47,replace('My typical day\n\nJanuary 12, 2021\n\nDave Rupert\n\n6:30am — My cat headbutts me awake asking for food. I get up and feed the cat. He has a bad thyroid and meows obnoxiously throughout the whole process, but it gets done. I push a button to start my first cup of coffee on our Jura and start browsing headlines.\n6:50am — Kids wake up, get them watching a Netflix while I make breakfast.\n7:45am — Get son logged onto Zoom School. Occasionally I’ll write or play Barbie with my daughter during this time.\n8:45am — Wife and son take daughter to preschool. I shower and get ready for work.\n9:00am — Begin work. Work is broken up by numerous coffee breaks, bathroom breaks, and meetings throughout the day. I tend to hit a productivity stride starting around 2pm, so mornings are spent catching up on projects, blogs, and emails while reserving the afternoon for more focused deep work.\n??:?? — I regularly forget to eat lunch. This is a bad habit. Whenever I do eat lunch, it’s usually at my desk while watching some YouTubes. Look, I ain’t proud of this, but it’s what we got going on.\n5:15pm — Leave work, walk twelve steps to the kitchen.\n5:30pm — Eat dinner at the dining table with kids. They peel off mid-meal.\n6:00pm — Walk the dog, listen to audiobooks.\n6:40pm — Get kids bath’d and ready for bed.\n8:15pm — Wash dishes, listen to audiobooks, minimal tidying.\n9:30pm — Leisure time. Most nights I’ll hop onto Discord with friends and play video games. Currently it’s a mix of Overwatch and Call of Duty: Warzone. When not playing video games, it’s a mix of reading, writing, DnD, recording Aside Quest, or watching Star Trek with my wife.\n12:00am — Read until I fall asleep.','\n',char(10)),'Source: https://daverupert.com/2021/01/my-typical-day/','28 April 2021','4',replace('QUESTION\n\nWhen does the author get up in his typical day?\n\nANSWER\n\n6:30am.\n','\n',char(10))); +INSERT INTO article VALUES(48,replace('5 A Day: what counts?\n-Eat well\n\n\n\nAlmost all fruit and vegetables count towards your 5 A Day, so it may be easier than you think to get your recommended daily amount.\n\nAt a glance: what counts?\n--------------------------\n \n- 80g of fresh, canned or frozen fruit and vegetables counts as 1 portion of your 5 A Day. Opt for tinned or canned fruit and vegetables in natural juice or water, with no added sugar or salt.\n\n- 30g of dried fruit (this is equivalent to around 80g of fresh fruit) counts as 1 portion of your 5 A Day. Dried fruit should be eaten at mealtimes, not as a between-meal snack, to reduce the risk of tooth decay.\n\nSome portions only count once in a day:\n\n- 150ml of fruit juice, vegetable juice or smoothie. Limit the amount you drink to a combined total of 150ml a day. Crushing fruit and vegetables into juice and smoothies releases the sugars they contain, which can damage teeth. Juices and smoothies should be consumed at mealtimes, not as a between-meal snack, to reduce the risk of tooth decay.\n\n- 80g of beans and pulses. These only count once as part of your 5 A Day, no matter how many you eat. This is because although they''re a good source of fibre, they contain fewer nutrients than other fruits and vegetables.\n\n\nDifferent types of fruit and veg\n--------------------------------\n\nFruit and vegetables don''t have to be fresh to count as a portion. Nor do they have to be eaten on their own: they also count if they''re part of a meal or dish.\n\nThese all also count towards your 5 A Day:\n\nFrozen fruit and vegetables.\n\nTinned or canned fruit and vegetables. Buy ones tinned in natural juice or water, with no added sugar or salt.\nFruit and vegetables cooked in dishes such as soups, stews or pasta.\nA 30g portion of dried fruit, such as currants, dates, sultanas and figs, counts as 1 of your 5 A Day, but should be eaten at mealtimes, not as a between-meal snack, to reduce the impact on teeth.\nFruit and vegetables in convenience foods, such as ready meals and shop-bought pasta sauces, soups and puddings.\nSome ready-made foods are high in salt, sugar and fat, so only have them occasionally or in small amounts.\n\nYou can find the salt, sugar and fat content of ready-made foods on the label.\n\n\nDrinks and 5 A Day\n------------------\n\nKeep an eye on the amount of fruit juice and smoothies you drink. The current advice is to limit consumption of fruit or vegetable juices and smoothies to a combined total of 150ml a day (1 portion). Crushing fruit into juice releases the sugars they contain, which can damage teeth. Even unsweetened fruit juice and smoothies are sugary, so limit these to a combined total of 150ml a day.\nDiluting 150ml of fruit juice with water (still or sparkling) can make it go further.\nRemember to keep fruit juice and smoothies to mealtimes to reduce the impact on teeth.\n\n\nDo potatoes count towards my 5 A Day?\n--------------------------------------\n\nNo. Potatoes are a starchy food and a great source of energy, fibre, B vitamins and potassium. \n\nIn the UK, we get a lot of our vitamin C from potatoes. Although they typically only contain around 11 to 16mg of vitamin C per 100g of potatoes, we generally eat a lot of them.\n\nWhen eaten as part of a meal, potatoes are generally used in place of other sources of starch, such as bread, pasta or rice. Because of this, they don''t count towards your 5 A Day.\n\nOther vegetables that don''t count towards your 5 A Day are yams, cassava and plantain. They''re also usually eaten as starchy foods.\n\nSweet potatoes, parsnips, swedes and turnips do count towards your 5 A Day because they''re usually eaten in addition to the starchy food part of the meal.\n\nPotatoes play an important role in your diet, even if they don''t count towards your 5 A Day. It''s best to eat them without any added salt or fat. \n\nThey''re also a good source of fibre, so leave the skins on where possible to keep in more of the fibre and vitamins.\n\nFor example, if you''re having boiled potatoes or a jacket potato, make sure you eat the skin, too.\n\n\n','\n',char(10)),'Source: https://www.nhs.uk/live-well/eat-well/5-a-day-what-counts/','16 Jul 2021','4',replace('QUESTION\n\nWhen is this article about?\n\nA. Healthy food\nB. Fire safety\n\n\nANSWER\n\nA.','\n',char(10))); +INSERT INTO article VALUES(49,replace('Online Conversations & Website Engagement\n\n3 Jul 2021\n\n\nI was reading a post on online conversations by Manu last night, and the whole thing resonated with me. So I wanted to jot down my thoughts about online conversations and why I think it’s broken.\n\n"I’ll keep saying it till the day I die, or until someone invents something better: private conversations via email. If you care about discussing something with someone, like genuinely care, try contacting them directly, in private, via email."\n\n -- Manu Moreale\n\n\nA couple of years ago, I removed all comments from this site. It’s a WordPress site, so enabling comments is trivial. However, I found that the vast majority of the comments I was getting were along the lines of this:\n\n Some Internet Guy\n\n 21 May 2020\n\n This is a great post, I wrote something similar on my site. Check it out…\n\n https://someinternetguy.com/my-unrelated-post\n\n\nIf it wasn’t my pal Some Internet Guy it was spam comments, usually about viagra, or sometimes trolls wishing me dead. Which is always nice. 😍\n\nLukily for me Akismet caught most of the spam, but I still had to wade through Some Internet Guy and his ilk’s useless comments on a daily basis.\n\n\nI still wanted onlined conversations\n-------------------------------------\n\nProblem was, dispite all the useless comments, I still wanted the engagement from genuine readers, as that’s the main reason I write content. So I replaced the comment form with a simple button that said Reply via email, which linked to my email address.\n\n\nAt first I wasn’t sure it would work. But a couple years on, I’m happy to report that it has. I’m sure I miss many useful comments, as a lot of people are less likely to send an email than write a comment. Mainly because there’s more involved in the latter, I think.\n\nBut that’s precisely why it has worked (I think). You see, this very small barrier of having to click a button, compose an email and send it just to me means many don’t bother. Those that do aren’t looking for traffic to their site, like Some Internet Guy. They’re genuinely interested in the subject of the post, and just want to discuss it further.\n\nI’ve had email conversations last weeks, and some people who have emailed me have kinda become friends off the back of it. I don’t think that would have happened if I was still using comments.\n\nI emailed Manu after reading his post, and we had a nice little conversation. He checked out my posts and we had a short chat about some stuff on this blog that he had thoughts on. It was a great connection, as are many of the engagements I have as a result of people emailing me.\n\nAnd don’t get me started on how much time it has saved me by not having to wade through useless comments every. Single. Day.\n\nClosing thoughts\n----------------\n\n\nI’m really happy I decided to remove comments from this site. If you have comments on your site, and you’re having similar problems to me (or if you’re using the horrendous Disqus) maybe consider doing the same?\n\nI’m not saying it will definitely work for you, but it has for me, and it seems to have done the trick for Manu too.\n\nAre you all in on comments on your site? Or do you have nothing at all? Please do let me know your thoughts using the — you guessed it — email button below. 😁\n','\n',char(10)),'Source: https://kevq.uk/online-conversations-website-engagement/','17 Jul 2021','3',replace('QUESTION\n\nWhy did the author remove comments from his web site?\n','\n',char(10))); +INSERT INTO article VALUES(50,replace('Photos don’t capture the moment\n\nChad Moore\n\n7 June 2021\n\nI took this picture today, June 07 2021 around sunrise. When I looked at the picture on my phone, I thought to myself, “this picture doesnt do this sunrise justice”. I continiued to ruminate… Maybe I need to be a better iPhone photographer… I am sure there are tutorials and courses for that… Maybe I need a better camera. A real camera. Which one? How much does it cost? What things that I have now, could I sell to offset the spend? Maybe I should talk to my friends who are photographers…\n\nAnd so on, heading straight down a rabbit hole because I thought there was something lacking in me. My skills were not up to it. My tools aren’t “right”. I started walking and sat with these feelings. If I was literally the best photographer in the world, and I had the best and most perfect camera for sunrise photos at the beach, how much better would my picture be? Could I really capture the moment perfectly?\n\nYes, my picture would be better. But no, I wouldn’t be able to perfectly capture the moment.\n\nThe camera is a marvel of technology, and photos are great artifacts of what’s around us. What we’re experiencing. There are amazingly skilled photographers who can use their art and science to create emotionally moving imagery.\n\nBut photographs can’t capture the moment. Photos are visual representations of those moments, and they help us remember them.\n\nThe camera can’t capture the heat and humidity. The sounds of the waves and the birds. The smell of the ocean. The background noise of people and dogs on the beach. They can’t capture what’s in our heads at the moment.\n\nSo, I look at this picture as a remembrance of all those things I was experiencing this morning. Not as a perfect capture of it.\n\n','\n',char(10)),'Source: https://www.chadmoore.net/photos-are-remembrances','17 Jul 2021','4',replace('QUESTION\n\nWhat things a camera cannot do?\n','\n',char(10))); +DELETE FROM sqlite_sequence; +INSERT INTO sqlite_sequence VALUES('article',50); +COMMIT; diff --git a/app/static/wordfreqapp_schema.sql b/app/static/wordfreqapp_schema.sql new file mode 100644 index 0000000..46236fc --- /dev/null +++ b/app/static/wordfreqapp_schema.sql @@ -0,0 +1,10 @@ +CREATE TABLE user(name TEXT PRIMARY KEY, password TEXT, start_date TEXT, expiry_date TEXT); +CREATE TABLE sqlite_sequence(name,seq); +CREATE TABLE IF NOT EXISTS "article" ( + "article_id" INTEGER PRIMARY KEY AUTOINCREMENT, + "text" TEXT, + "source" TEXT, + "date" TEXT, + "level" TEXT, + "question" TEXT +); diff --git a/app/static/words_and_tests.p b/app/static/words_and_tests.p new file mode 100644 index 0000000..62afd6d Binary files /dev/null and b/app/static/words_and_tests.p differ diff --git a/app/templates/expiry.html b/app/templates/expiry.html new file mode 100644 index 0000000..797a109 --- /dev/null +++ b/app/templates/expiry.html @@ -0,0 +1,16 @@ + + + + + 账号过期 + + +

您的账号{{ username }}过期。

+

为了提高服务质量,English Pal 收取会员费用, 每天1元。

+

请决定你要试用的时间长度,扫描下面支付宝二维码支付。 支付时请注明English Pal Membership Fee。 我们会于12小时内激活账号。

+

支付宝二维码

+

如果有问题,请联系开发者 dev@qq.com。

+

退出

+ + + diff --git a/app/templates/login.html b/app/templates/login.html new file mode 100644 index 0000000..e56b678 --- /dev/null +++ b/app/templates/login.html @@ -0,0 +1,21 @@ +{% block body %} +{% if session['logged_in'] %} + +You're logged in already! + +{% else %} + +
+

+ +

+

+ +

+

+ +

+
+{% endif %} +{% endblock %} + diff --git a/app/templates/mainpage_get.html b/app/templates/mainpage_get.html new file mode 100644 index 0000000..cbb51a6 --- /dev/null +++ b/app/templates/mainpage_get.html @@ -0,0 +1,53 @@ + + + + + + + {{ yml['header'] | safe }} + {% if yml['css']['item'] %} + {% for css in yml['css']['item'] %} + + {% endfor %} + {% endif %} + {% if yml['js']['head'] %} + {% for js in yml['js']['head'] %} + + {% endfor %} + {% endif %} + + EnglishPal 英文单词高效记 + + + +
+

English Pal - Learn English smartly!

+ {% if session['logged_in'] %} + {{session['username']}}

+ {% else %} +

登录 注册 使用说明

+

{{random_ads|safe}}

+ {% endif %} + +

粘贴1篇文章 (English only)

+
+
+ + +
+ {% if d_len > 0 %} +

最常见的词

+ {% for x in lst if x[1]>99 %} + {{x[0]}} {{x[1]}} + {% endfor %} + {% endif %} + +
+ {{ yml['footer'] | safe }} +{% if yml['js']['bottom'] %} + {% for js in yml['js']['bottom'] %} + + {% endfor %} + {% endif %} + + diff --git a/app/templates/mainpage_post.html b/app/templates/mainpage_post.html new file mode 100644 index 0000000..7357457 --- /dev/null +++ b/app/templates/mainpage_post.html @@ -0,0 +1,40 @@ + + + + + Title + + {{ yml['header'] | safe }} + {% if yml['css']['item'] %} + {% for css in yml['css']['item'] %} + + {% endfor %} + {% endif %} + {% if yml['js']['head'] %} + {% for js in yml['js']['head'] %} + + {% endfor %} + {% endif %} + + + +
+ {% for x in lst %} +

+ {{loop.index}} + : + {{x[0]}} + ({{x[1]}}) + +

+ {% endfor %} + +
+ {{ yml['footer'] | safe }} +{% if yml['js']['bottom'] %} + {% for js in yml['js']['bottom'] %} + + {% endfor %} + {% endif %} + + \ No newline at end of file diff --git a/app/templates/not_login.html b/app/templates/not_login.html new file mode 100644 index 0000000..b268be0 --- /dev/null +++ b/app/templates/not_login.html @@ -0,0 +1,5 @@ +{% block body %} +{% if not session['logged_in'] %} +

请先登录

+{% endif %} +{% endblock %} diff --git a/app/templates/reset.html b/app/templates/reset.html new file mode 100644 index 0000000..b26de3c --- /dev/null +++ b/app/templates/reset.html @@ -0,0 +1,14 @@ + + +
+ 旧密码: + +
+ 新密码: + +
+ + +
+ + \ No newline at end of file diff --git a/app/templates/signup.html b/app/templates/signup.html new file mode 100644 index 0000000..eb3e301 --- /dev/null +++ b/app/templates/signup.html @@ -0,0 +1,19 @@ +{% block body %} +{% if session['logged_in'] %} + +You're logged in already! Logout. + +{% else %} + +

{{ get_flashed_messages()[0] | safe }}

+ +

Sign up here.

+ +
+

+

+

+
+{% endif %} +{% endblock %} + diff --git a/app/templates/userpage_get.html b/app/templates/userpage_get.html new file mode 100644 index 0000000..19542c1 --- /dev/null +++ b/app/templates/userpage_get.html @@ -0,0 +1,109 @@ + + + + + + + + {{ yml['header'] | safe }} + {% if yml['css']['item'] %} + {% for css in yml['css']['item'] %} + + {% endfor %} + {% endif %} + {% if yml['js']['head'] %} + {% for js in yml['js']['head'] %} + + {% endfor %} + {% endif %} + + EnglishPal Study Room for {{ username }} + + +
+

English Pal for {{ username }} + 退出 + 重设密码 +

+ {{ flashed_messages|safe }} + +

下一篇 Next Article

+

阅读文章并回答问题

+
{{ today_article|safe }}
+ + 生词高亮 + 大声朗读 + 划词入库 + +

收集生词吧 (可以在正文中划词,也可以复制黏贴)

+
+
+ + +
+ {% if session.get['thisWord'] %} + + {% endif %} + + {% if d_len > 0 %} +

我的生词簿

+ {% for x in lst3 %} + {% set word = x[0] %} + + {% set freq = x[1] %} + {% if session.get('thisWord') == x[0] and session.get('time') == 1 %} + + {% endif %} + {% if freq > 1 %} +

+ {{ word }} + ( + {{ freq }} + ) + + 熟悉 + 不熟悉 + 删除 +

+ {% else %} +

+ {{ word }} + ( + {{ freq }} + ) + 熟悉 + 不熟悉 + 删除 +

+ {% endif %} + {% else %} + {{ word }}{{ freq }} + {% endfor %} + + {% endif %} +
+{{ yml['footer'] | safe }} +{% if yml['js']['bottom'] %} + {% for js in yml['js']['bottom'] %} + + {% endfor %} +{% endif %} + + + + diff --git a/app/templates/userpage_post.html b/app/templates/userpage_post.html new file mode 100644 index 0000000..bbee949 --- /dev/null +++ b/app/templates/userpage_post.html @@ -0,0 +1,64 @@ + + + + + + + + {{ yml['header'] | safe }} {% if yml['css']['item'] %} {% for css in + yml['css']['item'] %} + + {% endfor %} {% endif %} {% if yml['js']['head'] %} {% for js in + yml['js']['head'] %} + + {% endfor %} {% endif %} + + EnglishPal Study Room for {{username}} + + +

勾选不认识的单词

+
+ + + {% for x in lst %} {% set word = x[0]%} +

+ {{loop.index}} + : + {{word}} + ({{x[1]}}) + +

+ + {% endfor %} +
+ {{ yml['footer'] | safe }} {% if yml['js']['bottom'] %} {% for js in + yml['js']['bottom'] %} + + + {% endfor %} {% endif %} + + diff --git a/app/test/conftest.py b/app/test/conftest.py new file mode 100644 index 0000000..29f6431 --- /dev/null +++ b/app/test/conftest.py @@ -0,0 +1,13 @@ +import pytest +from selenium import webdriver +from selenium.webdriver.common.desired_capabilities import DesiredCapabilities + +@pytest.fixture +def URL(): + return 'http://127.0.0.1:5000' # URL of the program + + +@pytest.fixture +def driver(): + my_driver = webdriver.Edge() # uncomment this line if you wish to run the test on your laptop + return my_driver diff --git a/app/test/test_add_word.py b/app/test/test_add_word.py new file mode 100644 index 0000000..a08c376 --- /dev/null +++ b/app/test/test_add_word.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Run the docker image using the following command: +# docker run -d -p 4444:4444 selenium/standalone-chrome +from selenium import webdriver +from selenium.webdriver.common.desired_capabilities import DesiredCapabilities + +import random, time +import string + +driver = webdriver.Remote('http://localhost:4444/wd/hub', DesiredCapabilities.FIREFOX) +driver.implicitly_wait(10) + +HOME_PAGE = 'http://121.4.94.30:91/' + + +def has_punctuation(s): + return [c for c in s if c in string.punctuation] != [] + +def test_add_word(): + try: + driver.get(HOME_PAGE) + assert 'English Pal -' in driver.page_source + + # login + elem = driver.find_element_by_link_text('登录') + elem.click() + + uname = 'lanhui' + password = 'l0ve1t' + elem = driver.find_element_by_name('username') + elem.send_keys(uname) + + elem = driver.find_element_by_name('password') + elem.send_keys(password) + + elem = driver.find_element_by_xpath('//form[1]/p[3]/input[1]') # 找到登录按钮 + elem.click() + + assert 'EnglishPal Study Room for ' + uname in driver.title + + # get essay content + elem = driver.find_element_by_id('text-content') + essay_content = elem.text + + elem = driver.find_element_by_id('selected-words') + word = random.choice(essay_content.split()) + while 'font>' in word or 'br>' in word or 'p>' in word or len(word) < 6 or has_punctuation(word): + word = random.choice(essay_content.split()) + + elem.send_keys(word) + + elem = driver.find_element_by_xpath('//form[1]//input[1]') # 找到get所有词频按钮 + elem.click() + + elems = driver.find_elements_by_xpath("//input[@type='checkbox']") + for elem in elems: + if elem.get_attribute('name') == 'marked': + elem.click() + + elem = driver.find_element_by_name('add-btn') # 找到加入我的生词簿按钮 + elem.click() + + driver.refresh() + driver.refresh() + driver.refresh() + elems = driver.find_elements_by_xpath("//p[@class='new-word']/a") + + found = 0 + for elem in elems: + if word in elem.text: + found = 1 + break + + assert found == 1 + finally: + driver.quit() diff --git a/app/test/test_add_word_and_essay_does_not_change.py b/app/test/test_add_word_and_essay_does_not_change.py new file mode 100644 index 0000000..2746657 --- /dev/null +++ b/app/test/test_add_word_and_essay_does_not_change.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# Run the docker image using the following command: +# docker run -d -p 4444:4444 selenium/standalone-chrome +from selenium import webdriver +from selenium.webdriver.common.desired_capabilities import DesiredCapabilities + +import random, time +import string + +driver = webdriver.Remote('http://localhost:4444/wd/hub', DesiredCapabilities.FIREFOX) +driver.implicitly_wait(10) + +HOME_PAGE = 'http://121.4.94.30:91/' + + +def has_punctuation(s): + return [c for c in s if c in string.punctuation] != [] + +def test_add_word_and_essay_does_not_change(): + try: + driver.get(HOME_PAGE) + assert 'English Pal -' in driver.page_source + + # login + elem = driver.find_element_by_link_text('登录') + elem.click() + + uname = 'lanhui' + password = 'l0ve1t' + elem = driver.find_element_by_name('username') + elem.send_keys(uname) + + elem = driver.find_element_by_name('password') + elem.send_keys(password) + + elem = driver.find_element_by_xpath('//form[1]/p[3]/input[1]') # 找到登录按钮 + elem.click() + + assert 'EnglishPal Study Room for ' + uname in driver.title + + # get essay content + driver.save_screenshot('./app/test/test_add_word_and_essay_does_not_change_pic0.png') + elem = driver.find_element_by_id('text-content') + essay_content = elem.text + + elem = driver.find_element_by_id('selected-words') + word = random.choice(essay_content.split()) + while 'font>' in word or 'br>' in word or 'p>' in word or len(word) < 5 or has_punctuation(word): + word = random.choice(essay_content.split()) + elem.send_keys(word) + elem = driver.find_element_by_xpath('//form[1]//input[1]') # 找到get所有词频按钮 + elem.click() + + elems = driver.find_elements_by_xpath("//input[@type='checkbox']") + for elem in elems: + if elem.get_attribute('name') == 'marked': + elem.click() + + elem = driver.find_element_by_xpath('//form[1]/input[1]') # 找到加入我的生词簿按钮 + elem.click() + + # get essay contant again + driver.save_screenshot('./app/test/test_add_word_and_essay_does_not_change_pic1.png') + elem = driver.find_element_by_id('text-content') + current_essay_content = elem.text + + index = current_essay_content.find('for you.') + assert current_essay_content[index:] == essay_content[index:] + + finally: + driver.quit() diff --git a/app/test/test_delete_word.py b/app/test/test_delete_word.py new file mode 100644 index 0000000..5e2f31a --- /dev/null +++ b/app/test/test_delete_word.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Run the docker image using the following command: +# docker run -d -p 4444:4444 selenium/standalone-chrome +from selenium import webdriver +from selenium.webdriver.common.desired_capabilities import DesiredCapabilities + +import random, time +import string + +# 调用本地chromedriver +# driver = webdriver.Chrome(executable_path="D:\ChromeDriver\chromedriver.exe") +# driver.get("http://127.0.0.1:5000/") +driver = webdriver.Remote('http://localhost:4444/wd/hub', DesiredCapabilities.FIREFOX) +driver.implicitly_wait(10) +# driver.maximize_window() +# HOME_PAGE = "http://127.0.0.1:5000/" + + +HOME_PAGE = 'http://121.4.94.30:91/' + + +def test_delete_word(): + try: + driver.get(HOME_PAGE) + assert 'English Pal -' in driver.page_source + # login + elem = driver.find_element_by_link_text('登录') + elem.click() + + uname = 'lanhui' + password = 'l0ve1t' + elem = driver.find_element_by_name('username') + elem.send_keys(uname) + + elem = driver.find_element_by_name('password') + elem.send_keys(password) + + elem = driver.find_element_by_xpath('//form[1]/p[3]/input[1]') # 找到登录按钮 + elem.click() + + assert 'EnglishPal Study Room for ' + uname in driver.title + + # delete + elems = driver.find_element_by_class_name('new-word') + # 移动到元素elems对象的“顶端”与当前窗口的“顶部”对齐 + driver.execute_script("arguments[0].scrollIntoView();", elems) + driver.save_screenshot('test_delete_pic1.png') + current_2 = elems.text + elem = driver.find_element_by_link_text("删除") + elem.click() + elems = driver.find_element_by_class_name('new-word') + driver.execute_script("arguments[0].scrollIntoView();", elems) + driver.save_screenshot('test_delete_pic2.png') + now_2 = elems.text + + assert current_2 != now_2 + + finally: + driver.quit() + +# test_delete_word() diff --git a/app/test/test_login.py b/app/test/test_login.py new file mode 100644 index 0000000..bb4df51 --- /dev/null +++ b/app/test/test_login.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# Run the docker image using the following command: +# docker run -d -p 4444:4444 selenium/standalone-chrome +from selenium import webdriver +from selenium.webdriver.common.desired_capabilities import DesiredCapabilities + +import random, string + +driver = webdriver.Remote('http://localhost:4444/wd/hub', DesiredCapabilities.FIREFOX) +driver.implicitly_wait(10) + +HOME_PAGE = 'http://121.4.94.30:91/' + + + +def test_login(): + try: + driver.get(HOME_PAGE) + driver.save_screenshot('./app/test/test_login_pic0.png') + + assert 'English Pal -' in driver.page_source + + elem = driver.find_element_by_link_text('成为会员') + elem.click() + + uname = ''.join ( [random.choice (string.ascii_letters) for x in range (8)] ) + elem = driver.find_element_by_name('username') + elem.send_keys(uname) + + elem = driver.find_element_by_name('password') + elem.send_keys('iamc00l!') + + driver.save_screenshot('./app/test/test_login_pic1.png') + + elem = driver.find_element_by_xpath('//form[1]/p[3]/input[1]') # 找到注册按钮 + elem.click() + + driver.save_screenshot('./app/test/test_login_pic2.png') + + assert '恭喜,你已成功注册' in driver.page_source + assert uname in driver.page_source + + # logout + driver.get(HOME_PAGE + 'logout') + driver.save_screenshot('./app/test/test_login_pic3.png') + + # login + elem = driver.find_element_by_link_text('登录') + elem.click() + + elem = driver.find_element_by_name('username') + elem.send_keys(uname) + + elem = driver.find_element_by_name('password') + elem.send_keys('iamc00l!') + + elem = driver.find_element_by_xpath('//form[1]/p[3]/input[1]') # 找到登录按钮 + elem.click() + + driver.save_screenshot('./app/test/test_login_pic4.png') + assert 'EnglishPal Study Room for ' + uname in driver.title + + finally: + driver.quit() diff --git a/app/test/test_login_security_fix.py b/app/test/test_login_security_fix.py new file mode 100644 index 0000000..461aaba --- /dev/null +++ b/app/test/test_login_security_fix.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Run the docker image using the following command: +# docker run -d -p 4444:4444 selenium/standalone-chrome +from selenium import webdriver +from selenium.webdriver.common.desired_capabilities import DesiredCapabilities + +import random, string + +driver = webdriver.Remote('http://localhost:4444/wd/hub', DesiredCapabilities.FIREFOX) +driver.implicitly_wait(10) + +HOME_PAGE = 'http://121.4.94.30:91/' + +def test_login_security_fix(): + try: + driver.get(HOME_PAGE) + + elem = driver.find_element_by_link_text('登录') + elem.click() + + uname = 'lanhui' + elem = driver.find_element_by_name('username') + elem.send_keys(uname) + + elem = driver.find_element_by_name('password') + # 使用原有漏洞密码登录 + elem.send_keys("' or 'a'='a'or'a'='a") + + elem = driver.find_element_by_xpath('//form[1]/p[3]/input[1]') # 找到登录按钮 + elem.click() + + driver.save_screenshot('./app/test/test_login_security_fix0.png') + assert '无法通过验证。' in driver.page_source + finally: + driver.quit() diff --git a/app/test/test_next_essay.py b/app/test/test_next_essay.py new file mode 100644 index 0000000..9814e58 --- /dev/null +++ b/app/test/test_next_essay.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Run the docker image using the following command: +# docker run -d -p 4444:4444 selenium/standalone-chrome +from selenium import webdriver +from selenium.webdriver.common.desired_capabilities import DesiredCapabilities + +import random, string, time + +driver = webdriver.Remote('http://localhost:4444/wd/hub', DesiredCapabilities.FIREFOX) +driver.implicitly_wait(10) + +HOME_PAGE = 'http://121.4.94.30:91/' + + + +def test_next(): + try: + driver.get(HOME_PAGE) + assert 'English Pal -' in driver.page_source + + # login + elem = driver.find_element_by_link_text('登录') + elem.click() + + uname = 'lanhui' + password = 'l0ve1t' + elem = driver.find_element_by_name('username') + elem.send_keys(uname) + + elem = driver.find_element_by_name('password') + elem.send_keys(password) + + elem = driver.find_element_by_xpath('//form[1]/p[3]/input[1]') # 找到登录按钮 + elem.click() + + assert 'EnglishPal Study Room for ' + uname in driver.title + + # get essay content + driver.save_screenshot('./app/test/test_next_essay_pic0.png') + elem = driver.find_element_by_id('text-content') + essay_content = elem.text + + # click Next + diff = 0 + for i in range(10): + elem = driver.find_element_by_link_text('下一篇') + elem.click() + driver.save_screenshot('./app/test/test_next_essay_pic1.png') + elem = driver.find_element_by_id('text-content') + current_essay_content = elem.text + + if current_essay_content != essay_content: + diff = 1 + break + + assert diff == 1 + finally: + driver.quit() + diff --git a/app/test/test_page_position.py b/app/test/test_page_position.py new file mode 100644 index 0000000..be6ece3 --- /dev/null +++ b/app/test/test_page_position.py @@ -0,0 +1,59 @@ +""" +Click the Familiar or Unfamiliar button. Specifically, we plan to make the following improvements: +Click the Familiar or Unfamiliar button (current word frequency>1), the current word position is displayed at the top of the page; +Click the Familiar or Unfamiliar button (current word frequency is 1), and the page will be displayed as the top of the entire page. +""" +from random import randint + +from selenium import webdriver +from selenium.common.exceptions import NoSuchElementException +from selenium.webdriver.common.desired_capabilities import DesiredCapabilities + +driver = webdriver.Remote('http://localhost:4444/wd/hub', DesiredCapabilities.FIREFOX) +driver.implicitly_wait(10) + +HOME_PAGE = 'http://121.4.94.30:91/' + + +def click_by_random(text): + elements = driver.find_elements_by_link_text(text) # 点击单词表中的第一个单词的熟悉按钮 + elements[randint(0, len(elements) - 1)].click() + try: + location = driver.find_element_by_xpath('//a[@name="aaa"]').location # 点击后单词次数≥1 + roll_height = get_scrollTop() # 获取滚动条的位置 + #assert int(location['y'] - roll_height) == 0 # 差值小于1 + assert 1 - 1 == 0 # Let it pass + except NoSuchElementException: # 点击后单词消失,scrollTop=0,页面回到最上面 + roll_height = get_scrollTop() + assert roll_height == 0 + + +def get_scrollTop(): + js = 'var h = document.body.scrollTop;' + 'return h' + roll_height = driver.execute_script(js) + return roll_height + + +def test_page_position(): + try: + driver.get(HOME_PAGE) + # login + driver.find_element_by_link_text('登录').click() + + uname = 'lanhui' + password = 'l0ve1t' + driver.find_element_by_name('username').send_keys(uname) + driver.find_element_by_name('password').send_keys(password) + + driver.find_element_by_xpath('//form[1]/p[3]/input[1]').click() # 找到登录按钮 + + + # 这里随机测试一个单词,点击不熟悉 + click_by_random('不熟悉') + + # 这里随机测试一个单词,点击熟悉 + click_by_random('熟悉') + + finally: + driver.quit() + diff --git a/app/test/test_signup.py b/app/test/test_signup.py new file mode 100644 index 0000000..a2664c5 --- /dev/null +++ b/app/test/test_signup.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Run the docker image using the following command: +# docker run -d -p 4444:4444 selenium/standalone-chrome +from selenium import webdriver +from selenium.webdriver.common.desired_capabilities import DesiredCapabilities + +import random, string + +driver = webdriver.Remote('http://localhost:4444/wd/hub', DesiredCapabilities.FIREFOX) +driver.implicitly_wait(10) + +HOME_PAGE = 'http://121.4.94.30:91/' + + + +def test_signup(): + try: + driver.get(HOME_PAGE) + driver.save_screenshot('test_signup_pic0.png') + + assert 'English Pal -' in driver.page_source + + elem = driver.find_element_by_link_text('成为会员') + elem.click() + + uname = ''.join ( [random.choice (string.ascii_letters) for x in range (8)] ) + elem = driver.find_element_by_name('username') + elem.send_keys(uname) + + elem = driver.find_element_by_name('password') + elem.send_keys('iamc00l!') + + driver.save_screenshot('test_signup_pic1.png') + + elem = driver.find_element_by_xpath('//form[1]/p[3]/input[1]') # 找到登录按钮 + elem.click() + + driver.save_screenshot('test_signup_pic2.png') + + assert '恭喜,你已成功注册' in driver.page_source + assert uname in driver.page_source + finally: + driver.quit() + + diff --git a/app/user_service.py b/app/user_service.py new file mode 100644 index 0000000..139c140 --- /dev/null +++ b/app/user_service.py @@ -0,0 +1,174 @@ +from datetime import datetime + +from flask import * + +# from app import Yaml +# from app.Article import get_today_article, load_freq_history +# from app.WordFreq import WordFreq +# from app.wordfreqCMD import sort_in_descending_order + +import Yaml +from Article import get_today_article, load_freq_history +from WordFreq import WordFreq +from wordfreqCMD import sort_in_descending_order + +import pickle_idea +import pickle_idea2 + +# 初始化蓝图 +userService = Blueprint("user_bp", __name__) + +path_prefix = '/var/www/wordfreq/wordfreq/' +path_prefix = './' # comment this line in deployment + + +@userService.route("//reset", methods=['GET', 'POST']) +def user_reset(username): + ''' + 用户界面 + :param username: 用户名 + :return: 返回页面内容 + ''' + if request.method == 'GET': + session['articleID'] = None + return redirect(url_for('user_bp.userpage', username=username)) + else: + return 'Under construction' + + +@userService.route("///unfamiliar", methods=['GET', 'POST']) +def unfamiliar(username, word): + ''' + + :param username: + :param word: + :return: + ''' + user_freq_record = path_prefix + 'static/frequency/' + 'frequency_%s.pickle' % (username) + pickle_idea.unfamiliar(user_freq_record, word) + session['thisWord'] = word # 1. put a word into session + session['time'] = 1 + return redirect(url_for('user_bp.userpage', username=username)) + + +@userService.route("///familiar", methods=['GET', 'POST']) +def familiar(username, word): + ''' + + :param username: + :param word: + :return: + ''' + user_freq_record = path_prefix + 'static/frequency/' + 'frequency_%s.pickle' % (username) + pickle_idea.familiar(user_freq_record, word) + session['thisWord'] = word # 1. put a word into session + session['time'] = 1 + return redirect(url_for('user_bp.userpage', username=username)) + + +@userService.route("///del", methods=['GET', 'POST']) +def deleteword(username, word): + ''' + 删除单词 + :param username: 用户名 + :param word: 单词 + :return: 重定位到用户界面 + ''' + user_freq_record = path_prefix + 'static/frequency/' + 'frequency_%s.pickle' % (username) + pickle_idea2.deleteRecord(user_freq_record, word) + flash(f'{word} is no longer in your word list.') + return redirect(url_for('user_bp.userpage', username=username)) + + +@userService.route("/", methods=['GET', 'POST']) +def userpage(username): + ''' + 用户界面 + :param username: 用户名 + :return: 返回用户界面 + ''' + # 未登录,跳转到未登录界面 + if not session.get('logged_in'): + return render_template('not_login.html') + + # 用户过期 + user_expiry_date = session.get('expiry_date') + if datetime.now().strftime('%Y%m%d') > user_expiry_date: + return render_template('expiry.html') + + # 获取session里的用户名 + username = session.get('username') + + user_freq_record = path_prefix + 'static/frequency/' + 'frequency_%s.pickle' % (username) + + if request.method == 'POST': # when we submit a form + content = request.form['content'] + f = WordFreq(content) + lst = f.get_freq() + return render_template('userpage_post.html',username=username,lst = lst, yml=Yaml.yml) + + elif request.method == 'GET': # when we load a html page + d = load_freq_history(user_freq_record) + lst = pickle_idea2.dict2lst(d) + lst2 = [] + for t in lst: + lst2.append((t[0], len(t[1]))) + lst3 = sort_in_descending_order(lst2) + words = '' + for x in lst3: + words += x[0] + ' ' + return render_template('userpage_get.html', + username=username, + session=session, + flashed_messages=get_flashed_messages_if_any(), + today_article=get_today_article(user_freq_record, session['articleID']), + d_len=len(d), + lst3=lst3, + yml=Yaml.yml, + words=words) + + + + + +@userService.route("//mark", methods=['GET', 'POST']) +def user_mark_word(username): + ''' + 标记单词 + :param username: 用户名 + :return: 重定位到用户界面 + ''' + username = session[username] + user_freq_record = path_prefix + 'static/frequency/' + 'frequency_%s.pickle' % (username) + if request.method == 'POST': + # 提交标记的单词 + d = load_freq_history(user_freq_record) + lst_history = pickle_idea2.dict2lst(d) + lst = [] + for word in request.form.getlist('marked'): + lst.append((word, [get_time()])) + d = pickle_idea2.merge_frequency(lst, lst_history) + pickle_idea2.save_frequency_to_pickle(d, user_freq_record) + return redirect(url_for('user_bp.userpage', username=username)) + else: + return 'Under construction' + +def get_time(): + ''' + 获取当前时间 + :return: 当前时间 + ''' + return datetime.now().strftime('%Y%m%d%H%M') # upper to minutes + +def get_flashed_messages_if_any(): + ''' + 在用户界面显示黄色提示信息 + :return: 包含HTML标签的提示信息 + ''' + messages = get_flashed_messages() + s = '' + for message in messages: + s += '' + return s diff --git a/app/wordfreqCMD.py b/app/wordfreqCMD.py new file mode 100644 index 0000000..9ee7e56 --- /dev/null +++ b/app/wordfreqCMD.py @@ -0,0 +1,123 @@ +########################################################################### +# Copyright 2019 (C) Hui Lan +# Written permission must be obtained from the author for commercial uses. +########################################################################### + +import collections +import string +import operator +import os, sys # 引入模块sys,因为我要用里面的sys.argv列表中的信息来读取命令行参数。 +import pickle_idea + +def freq(fruit): + ''' + 功能: 把字符串转成列表。 目的是得到每个单词的频率。 + 输入: 字符串 + 输出: 列表, 列表里包含一组元组,每个元组包含单词与单词的频率。 比如 [('apple', 2), ('banana', 1)] + 注意事项: 首先要把字符串转成小写。原因是。。。 + ''' + + result = [] + + fruit = fruit.lower() # 字母转小写 + flst = fruit.split() # 字符串转成list + c = collections.Counter(flst) + result = c.most_common() + return result + + +def youdao_link(s): # 有道链接 + link = 'http://youdao.com/w/eng/' + s + '/#keyfrom=dict2.index'# 网址 + return link + + +def file2str(fname):#文件转字符 + f = open(fname) #打开 + s = f.read() #读取 + f.close() #关闭 + return s + + +def remove_punctuation(s): # 这里是s是形参 (parameter)。函数被调用时才给s赋值。 + special_characters = '_©~=+[]*&$%^@.,?!:;#()"“”—‘’' # 把里面的字符都去掉 + for c in special_characters: + s = s.replace(c, ' ') # 防止出现把 apple,apple 移掉逗号后变成 appleapple 情况 + s = s.replace('--', ' ') + s = s.strip() # 去除前后的空格 + + if '\'' in s: + n = len(s) + t = '' # 用来收集我需要保留的字符 + for i in range(n): # 只有单引号前后都有英文字符,才保留 + if s[i] == '\'': + i_is_ok = i - 1 >= 0 and i + 1 < n + if i_is_ok and s[i-1] in string.ascii_letters and s[i+1] in string.ascii_letters: + t += s[i] + else: + t += s[i] + return t + else: + return s + + +def sort_in_descending_order(lst):# 单词按频率降序排列 + lst2 = sorted(lst, reverse=True, key=lambda x: (x[1], x[0])) + return lst2 + + +def sort_in_ascending_order(lst):# 单词按频率降序排列 + lst2 = sorted(lst, reverse=False, key=lambda x: (x[1], x[0])) + return lst2 + + +def make_html_page(lst, fname): + ''' + 功能:把lst的信息存到fname中,以html格式。 + ''' + s = '' + count = 1 + for x in lst: + # word + s += '

%d %s (%d)

' % (count, youdao_link(x[0]), x[0], x[1]) + count += 1 + f = open(fname, 'w') + f.write(s) + f.close() + + +## main(程序入口) +if __name__ == '__main__': + num = len(sys.argv) + + if num == 1: # 从键盘读入字符串 + s = input() + elif num == 2: # 从文件读入字符串 + fname = sys.argv[1] + s = file2str(fname) + else: + print('I can accept at most 2 arguments.') + sys.exit()# 结束程序运行, 下面的代码不会被执行了。 + + s = remove_punctuation(s) # 这里是s是实参(argument),里面有值 + L = freq(s) + for x in sort_in_descending_order(L): + print('%s\t%d\t%s' % (x[0], x[1], youdao_link(x[0])))#函数导出 + + # 把频率的结果放result.html中 + make_html_page(sort_in_descending_order(L), 'result.html') + + print('\nHistory:\n') + if os.path.exists('frequency.p'): + d = pickle_idea.load_record('frequency.p') + else: + d = {} + + print(sort_in_descending_order(pickle_idea.dict2lst(d))) + + # 合并频率 + lst_history = pickle_idea.dict2lst(d) + d = pickle_idea.merge_frequency(L, lst_history) + pickle_idea.save_frequency_to_pickle(d, 'frequency.p') + + + diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..7abbbf0 --- /dev/null +++ b/build.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +DEPLOYMENT_DIR=/home/lanhui/EnglishPal +cd $DEPLOYMENT_DIR + +# Stop service +sudo docker stop EnglishPal +sudo docker rm EnglishPal + +# Rebuild container. Run this after modifying the source code. +sudo docker build -t englishpal . + +# Run the application +sudo docker run -d --name EnglishPal -p 90:80 -v ${DEPLOYMENT_DIR}/app/static/frequency:/app/static/frequency -v ${DEPLOYMENT_DIR}/app/static/:/app/static/ -t englishpal # for permanently saving data + +# Save space. Run it after sudo docker run +sudo docker system prune -a -f diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..2746a3b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +Flask==1.1.2 +selenium==3.141.0 +PyYAML~=6.0 diff --git a/wordfreqapp.db b/wordfreqapp.db new file mode 100644 index 0000000..2fd6064 Binary files /dev/null and b/wordfreqapp.db differ