Initial commit

develop
Arno 2 months ago committed by Gitea
parent 0bd11c9668
commit 5e69d0e19c

Binary file not shown.

Binary file not shown.

@ -0,0 +1,13 @@
package Base;
public class Email_settings {
public static final String SMTP_HOST = "smtp.qq.com";
// 邮箱服务器端口
public static final String SMTP_PORT = "587";
// 发件人邮箱
public static final String FROM_EMAIL = "835981889@qq.com";
// 发件人邮箱授权码
public static final String EMAIL_PASSWORD = "fpqfprqznbvdbcdf";
// 是否启用SSL
public static final boolean SSL_ENABLE = true;
}

@ -0,0 +1,267 @@
package Base;
import java.util.HashMap;
import java.util.Random;
import java.util.Stack;
public class Question {
private int number;
private String content;
private String type;
private String answer;
private String[] options;
private final Random ra= new Random();
public static final HashMap<String, String> trigValues = new HashMap<>();
static {
// 15°
trigValues.put("sin(15°)", "√2*(√3-1)/4");
trigValues.put("cos(15°)", "√2*(√3+1)/4");
trigValues.put("tan(15°)", "(2-√3)");
trigValues.put("sin²(15°)", "(2-√3)/4");
trigValues.put("cos²(15°)", "(2+√3)/4");
trigValues.put("tan²(15°)", "(7-4*√3)");
// 22.5°
trigValues.put("sin(22.5°)", "√0.59/2"); //√(2-√2)/2
trigValues.put("cos(22.5°)", "√3.41/2"); //√(2+√2)/2
trigValues.put("tan(22.5°)", "(√2-1)");
trigValues.put("sin²(22.5°)", "(2-√2)/4");
trigValues.put("cos²(22.5°)", "(2+√2)/4");
trigValues.put("tan²(22.5°)", "(3-2*√2)");
// 75°
trigValues.put("sin(75°)", "√2*(√3+1)/4");
trigValues.put("cos(75°)", "√2*(√3-1)/4");
trigValues.put("tan(75°)", "(2+√3)");
trigValues.put("sin²(75°)", "(2+√3)/4");
trigValues.put("cos²(75°)", "(2-√3)/4");
trigValues.put("tan²(75°)", "(7+4*√3)");
// 105°
trigValues.put("sin(105°)", "√2*(√3+1)/4");
trigValues.put("cos(105°)", "√2*(1-√3)/4");
trigValues.put("tan(105°)", "(0-(2+√3))");
trigValues.put("sin²(105°)", "(2+√3)/4");
trigValues.put("cos²(105°)", "(2-√3)/4");
trigValues.put("tan²(105°)", "(7+4*√3)");
// 120°
trigValues.put("sin(120°)", "√3/2");
trigValues.put("cos(120°)", "(0-1/2)");
trigValues.put("tan(120°)", "(0-√3)");
trigValues.put("sin²(120°)", "3/4");
trigValues.put("cos²(120°)", "1/4");
trigValues.put("tan²(120°)", "3");
// 135°
trigValues.put("sin(135°)", "√2/2");
trigValues.put("cos(135°)", "(0-√2/2)");
trigValues.put("tan(135°)", "(0-1)");
trigValues.put("sin²(135°)", "1/2");
trigValues.put("cos²(135°)", "1/2");
trigValues.put("tan²(135°)", "1");
// 150°
trigValues.put("sin(150°)", "1/2");
trigValues.put("cos(150°)", "(0-√3/2)");
trigValues.put("tan(150°)", "(0-√3/3)");
trigValues.put("sin²(150°)", "1/4");
trigValues.put("cos²(150°)", "3/4");
trigValues.put("tan²(150°)", "1/3");
// 210°
trigValues.put("sin(210°)", "(0-1/2)");
trigValues.put("cos(210°)", "(0-√3/2)");
trigValues.put("tan(210°)", "√3/3");
trigValues.put("sin²(210°)", "1/4");
trigValues.put("cos²(210°)", "3/4");
trigValues.put("tan²(210°)", "1/3");
// 300°
trigValues.put("sin(300°)", "(0-√3/2)");
trigValues.put("cos(300°)", "1/2");
trigValues.put("tan(300°)", "(0-√3)");
trigValues.put("sin²(300°)", "3/4");
trigValues.put("cos²(300°)", "1/4");
trigValues.put("tan²(300°)", "3");
}
public Question(int number, String content, String type) {
this.number = number;
this.content = content;
this.type = type;
options=new String[4];
}
public int getNumber() { return number; }
public String getContent() { return content; }
public String getType() { return type; }
public String getAnswer() {return answer;}
public String getOptions(int i) {return options[i];}
@Override
public String toString(){
return this.number+". "+this.content+" = ?";
}
public void set_options(){
answer=calculate(this.content);
int which=ra.nextInt(4);
options[which]=answer;
for (int i=0;i<4;i++) {
if (i != which) {
if (this.type.equals("高中")) {
options[i] = answer.equals("不可解") ? String.format("%.2f", Math.sqrt(3) * ra.nextInt(10) + ra.nextDouble(1)) :
String.format("%.2f", Double.parseDouble(answer) + Math.sqrt(2) * ra.nextInt(5));
} else {
if (Double.parseDouble(answer) ==Math.floor(Double.parseDouble(answer)) ) {
options[i] = answer.equals("不可解") ? String.valueOf((int) ra.nextInt(1000) + ra.nextInt(10)) :
String.valueOf((int) Double.parseDouble(answer) + ra.nextInt(10));
} else {
options[i] = answer.equals("不可解") ? String.format("%.2f", ra.nextInt(1000) + ra.nextDouble(10)) :
String.format("%.2f", Double.parseDouble(answer) + ra.nextDouble(10));
}
}
for (int j = 0; j < i; j++) {
if (options[j].equals(options[i])) {
i--;
break;
}
}
if (options[i].equals(answer)) {
i--;
}
}
}
}
public String calculate(String question){
try {
String expr = question.replaceAll(" ", "");
double result;
if (!type.equals("高中")) {
result = deal_calculate(expr);
if (Double.isNaN(result) || Double.isInfinite(result)) {
return "不可解";
}
if (result == Math.floor(result)) {
return String.valueOf((int) result);
} else {
return String.format("%.2f", result);
}
}
else{
return deal_sen_calculate(expr);
}
} catch (Exception e) {
return "不可解";
}
}
private double deal_calculate(String expr){
Stack<Double> numbers = new Stack<>();
Stack<Character> operators = new Stack<>();
expr=expr.replace("²", "^2");
for (int i = 0; i < expr.length(); i++) {
char c = expr.charAt(i);
if (Character.isDigit(c)) {
StringBuilder temp = new StringBuilder();
while (i < expr.length() && (Character.isDigit(expr.charAt(i)) || expr.charAt(i) == '.')) {
temp.append(expr.charAt(i++));
}
i--;
numbers.push(Double.parseDouble(temp.toString()));
} else if (c == '(') {
operators.push(c);
} else if (c == ')') {
while (operators.peek() != '(') {
numbers.push(Deal_Operator(operators.pop(), numbers.pop(), numbers.pop()));
}
operators.pop();
} else if (isOperator(c)) {
while (!operators.isEmpty() && hasPrecedence(c, operators.peek())) {
numbers.push(Deal_Operator(operators.pop(), numbers.pop(), numbers.pop()));
}
operators.push(c);
}
else if (c == '√'){
i++;
StringBuilder temp = new StringBuilder();
while (i < expr.length() && (Character.isDigit(expr.charAt(i)) || expr.charAt(i) == '.')) {
temp.append(expr.charAt(i++));
}
i--;
numbers.push(Math.sqrt(Double.parseDouble(temp.toString())));
}
}
while (!operators.isEmpty()) {
numbers.push(Deal_Operator(operators.pop(), numbers.pop(), numbers.pop()));
}
return numbers.pop();
}
private String deal_sen_calculate(String m_expr){
try {
String expr = m_expr.replaceAll(" ", "");
StringBuilder result = new StringBuilder();
int i = 0;
while (i < expr.length()) {
char c = expr.charAt(i);
if (c == 's' || c == 'c' || c == 't') {
StringBuilder trigFunc = new StringBuilder();
while (i < expr.length() && expr.charAt(i) != ')') {
trigFunc.append(expr.charAt(i++));
}
trigFunc.append(')'); // 添加右括号
String trigKey = trigFunc.toString();
String trigValue = trigValues.get(trigKey);
if (trigValue != null) {
result.append(trigValue);
}
} else if (isOperator(c) || c == '(' || c == ')') {
result.append(c);
}
i++;
}
return String.format("%.2f",deal_calculate(Deal_Expression(result.toString())));
} catch (Exception e) {
return "不可解";
}
}
private double Deal_Operator(char operator, double b, double a) {
switch (operator) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': {
if (b == 0) throw new ArithmeticException("除零错误");
return a / b;
}
case '^': return Math.pow(a, b);
default: return 0;
}
}
private boolean isOperator(char c) {
return c == '+' || c == '-' || c == '*' || c == '/' || c == '^';
}
//检验运算优先级,来决定先计算再压栈还是直接压栈
private boolean hasPrecedence(char op1, char op2) {
if ( (op2 == '(' || op2 == ')')
|| ((op1 == '*' || op1 == '/') && (op2 == '+' || op2 == '-'))
|| (op1 == '^' && (op2 == '*' || op2 == '/' || op2 == '+' || op2 == '-'))) {
return false;
}
return true;
}
private String Deal_Expression(String expr) {
String simplified = expr.replace("+-","-");
simplified = simplified.replace("--","+");
return simplified;
}
}

@ -0,0 +1,32 @@
package Base;
public class User {
private String email;
private String password;
public User(String email) {
this.email = email;
}
public String get_email() { return email; }
public String get_password() { return password; }
public void set_password(String password) { this.password = password; }
public static boolean check_password(String password) {
if (password == null || password.length() < 6 || password.length() > 20) {
return false;
}
boolean hasUpper = false;
boolean hasLower = false;
boolean hasDigit = false;
for (char c : password.toCharArray()) {
if (Character.isUpperCase(c)) hasUpper = true;
if (Character.isLowerCase(c)) hasLower = true;
if (Character.isDigit(c)) hasDigit = true;
}
return hasUpper && hasLower && hasDigit;
}
}

@ -0,0 +1,8 @@
package Generator;
public interface G_ques {
String g_question();
String g_type();
char g_operator();
String add_brackets(StringBuilder s,int count);
}

@ -0,0 +1,82 @@
package Generator;
import java.util.Random;
public class Jun_g_ques implements G_ques{
private Random ra= new Random();
@Override
public String g_question() {
int count=ra.nextInt(5)+1;
StringBuilder question = new StringBuilder();
boolean flag=false;
for (int i=0;i<count;i++){
if (i>0){
question.append(" ").append(g_operator()).append(" ");
}
if (ra.nextDouble()<0.25) {
if (ra.nextBoolean()) {
question.append(ra.nextInt(30) + 1).append("²");
}
else {
question.append("√").append(ra.nextInt(100) + 1);
}
flag=true;
}
else {
question.append(ra.nextInt(100) + 1);
}
}
if (!flag){
if(count==1){
if (ra.nextBoolean()){
question.append("²");
}
else {
question.insert(0,"√");
}
}
else {
String[] parts = question.toString().split(" ");
int pos = ra.nextInt(count);
if (ra.nextBoolean()) {
parts[pos * 2] = parts[pos * 2] + "²";
} else {
parts[pos * 2] = "√" + parts[pos * 2];
}
question = new StringBuilder(String.join(" ", parts));
}
}
return add_brackets(question,count);
}
@Override
public String g_type(){
return "初中";
}
@Override
public char g_operator(){
char[] op={'+','-','*','/'};
return op[ra.nextInt(op.length)];
}
@Override
public String add_brackets(StringBuilder s,int count){
String res=s.toString();
String[] parts=s.toString().split(" ");
if (ra.nextBoolean()&&parts.length!=1) {
int num=ra.nextInt(3)+1;
for (int i=0;i<num;i++) {
int pos = ra.nextInt(count);
if (pos==count-1){
pos=pos-1;
}
parts[pos * 2] = "(" + parts[pos * 2];
parts[parts.length-1]=parts[parts.length-1]+")";
}
res = String.join(" ", parts);
}
return res;
}
}

@ -0,0 +1,44 @@
package Generator;
import java.util.Random;
public class Pri_g_ques implements G_ques{
private Random ra= new Random();
@Override
public String g_question() {
int count=ra.nextInt(4)+2;
StringBuilder question = new StringBuilder();
int count_bracket=0;
for (int i=0;i<count;i++) {
if (i > 0) {
question.append(" ").append(g_operator()).append(" ");
}
if (i!=count-1&&ra.nextDouble()<0.4){
question.append("(");
count_bracket++;
}
question.append(ra.nextInt(100) + 1);
}
if (count_bracket!=0){
question.append(")".repeat(Math.max(0, count_bracket)));
}
return question.toString();
}
@Override
public String g_type(){
return "小学";
}
@Override
public char g_operator(){
char[] op={'+','-','*','/'};
return op[ra.nextInt(op.length)];
}
@Override
public String add_brackets(StringBuilder s,int count){
return s.toString();
}
}

@ -0,0 +1,64 @@
package Generator;
import java.util.Random;
public class Sen_g_ques implements G_ques{
private Random ra= new Random();
@Override
public String g_question() {
int count=ra.nextInt(5)+1;
StringBuilder question = new StringBuilder();
for (int i=0;i<count;i++) {
if (i > 0) {
question.append(" ").append(g_operator()).append(" ");
}
if (ra.nextDouble()<0.3){
question.append(g_trig()).append("²").append("(").append(g_angle()).append("°)");
}
else {
question.append(g_trig()).append("(").append(g_angle()).append("°)");
}
}
return add_brackets(question,count);
}
@Override
public String g_type(){
return "高中";
}
@Override
public char g_operator(){
char[] op={'+','-','*','/'};
return op[ra.nextInt(op.length)];
}
public String g_trig(){
String[] trig={"sin","cos","tan"};
return trig[ra.nextInt(trig.length)];
}
public String g_angle(){
String[] angle={"15","22.5","75","105","120","135","150","210","300"};
return angle[ra.nextInt(angle.length)];
}
public String add_brackets(StringBuilder s,int count){
String res=s.toString();
String[] parts=s.toString().split(" ");
if (ra.nextBoolean()&&parts.length!=1) {
int num=ra.nextInt(3)+1;
for (int i=0;i<num;i++) {
int pos = ra.nextInt(count);
if (pos==count-1){
pos=pos-1;
}
parts[pos * 2] = "(" + parts[pos * 2];
parts[parts.length-1]=parts[parts.length-1]+")";
}
res = String.join(" ", parts);
}
return res;
}
}

@ -0,0 +1,53 @@
package Send_Email;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class Deal_i_code{
private static final Map<String, I_Code> codeMap = new ConcurrentHashMap<>();
private static class I_Code {
String code;
long createTime;
private static final long EXPIRATION_TIME = 5 * 60 * 1000;
I_Code(String code) {
this.code = code;
this.createTime = System.currentTimeMillis();
}
boolean isExpired() {
return System.currentTimeMillis() - createTime > EXPIRATION_TIME;
}
}
public static String generate_code(String email) {
String code = Generate_i_code.generateCode(6);
codeMap.put(email, new I_Code(code));
return code;
}
public static boolean judge_code(String email, String inputCode) {
I_Code codeInfo = codeMap.get(email);
if (codeInfo == null) {
return false;
}
if (codeInfo.isExpired()) {
codeMap.remove(email);
return false;
}
boolean isValid = codeInfo.code.equals(inputCode);
if (isValid) {
codeMap.remove(email);
}
return isValid;
}
public static void clean_codes() {
codeMap.entrySet().removeIf(entry -> entry.getValue().isExpired());
}
public static void clean_all_codes(){
codeMap.clear();
}
}

@ -0,0 +1,18 @@
package Send_Email;
import java.util.Random;
public class Generate_i_code {
public static String generateCode(int length) {
Random ra = new Random();
StringBuilder code = new StringBuilder();
for (int i = 0; i < length; i++) {
if (ra.nextBoolean()){
code.append((char)('A'+ra.nextInt(26)));
} else {
code.append((char)('0'+ra.nextInt(10)));
}
}
return code.toString();
}
}

@ -0,0 +1,107 @@
package Send_Email;
import Base.Email_settings;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;
import java.util.regex.Pattern;
public class Send_email {
public static boolean judge_email_address(String email) {
if (email == null || email.trim().isEmpty()) {
System.out.println("邮箱不能为空");
return false;
}
// 去除前后空格
email = email.trim();
// 检查长度
if (email.length() > 254) { // RFC标准规定邮箱最大长度
System.out.println("邮箱地址过长");
return false;
}
// 检查是否包含@
if (!email.contains("@")) {
System.out.println("邮箱格式错误:缺少@符号");
return false;
}
// 分割本地部分和域名部分
String[] parts = email.split("@");
if (parts.length != 2) {
System.out.println("邮箱格式错误:只能有一个@符号");
return false;
}
String localPart = parts[0];
String domainPart = parts[1];
// 验证本地部分
if (localPart.isEmpty()) {
System.out.println("邮箱格式错误:@前必须有内容");
return false;
}
if (localPart.length() > 64) {
System.out.println("邮箱格式错误:@前内容过长");
return false;
}
// 验证域名部分
if (domainPart.isEmpty()) {
System.out.println("邮箱格式错误:@后必须有内容");
return false;
}
if (!domainPart.contains(".")) {
System.out.println("邮箱格式错误:域名不完整");
return false;
}
// 验证顶级域名
String[] domainParts = domainPart.split("\\.");
String topLevelDomain = domainParts[domainParts.length - 1];
if (topLevelDomain.length() < 2) {
System.out.println("邮箱格式错误:顶级域名太短");
return false;
}
String emailRegex = "^(?=.{1,64}@)[A-Za-z0-9_-]+(\\.[A-Za-z0-9_-]+)*@"
+ "[^-][A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(\\.[A-Za-z]{2,})$";
boolean matches = Pattern.matches(emailRegex, email);
System.out.println(matches ? "" : "邮箱格式错误");
return matches;
}
public static boolean send_email(String toEmail, String Code) {
try {
Properties props = new Properties();
props.put("mail.smtp.host", Email_settings.SMTP_HOST);
props.put("mail.smtp.port", Email_settings.SMTP_PORT);
props.put("mail.smtp.auth", "true");
if (Email_settings.SSL_ENABLE) {
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.ssl.trust", Email_settings.SMTP_HOST);
}
// 创建会话
Session session = Session.getInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(Email_settings.FROM_EMAIL, Email_settings.EMAIL_PASSWORD);
}
});
// 创建邮件消息
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(Email_settings.FROM_EMAIL));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail));
message.setSubject("注册验证码");
// 邮件内容
String content = String.format(
"尊敬的用户:<b>%s</b><br/><br/>" +
"您的注册验证码是:<b>%s</b><br/><br/>" +
"验证码有效期为5分钟请尽快完成注册。<br/><br/>" +
"如果不是您本人操作,请忽略此邮件。",
toEmail,Code
);
message.setContent(content, "text/html;charset=UTF-8");
// 发送邮件
Transport.send(message);
return true;
} catch (Exception e) {
return false;
}
}
}

@ -0,0 +1,39 @@
package Service;
import Base.Question;
import Generator.G_ques;
import Generator.Jun_g_ques;
import Generator.Pri_g_ques;
import Generator.Sen_g_ques;
import java.util.ArrayList;
public class Generate_paper {
public static ArrayList<Question> g_paper(int num,String type) {
ArrayList<Question> result = new ArrayList<>();
G_ques generator;
switch (type){
case "小学":{
generator=new Pri_g_ques();
break;
}
case "初中":{
generator=new Jun_g_ques();
break;
}
case "高中":{
generator=new Sen_g_ques();
break;
}
default:{
generator=new Pri_g_ques();
}
}
for (int i=0;i<num;i++){
Question temp=new Question(i+1,generator.g_question(),generator.g_type());
temp.set_options();
result.add(temp);
}
return result;
}
}

@ -0,0 +1,93 @@
package Service;
import Base.User;
import java.io.*;
import java.util.ArrayList;
public class User_service {
private ArrayList<User> users;
private final String base_dir="用户/";
public User_service() {
if (!load_users()){
users=new ArrayList<>();
}
}
public String change_pwd(String email, String oldPassword, String newPassword){
User user=find_user(email);
if (user == null) {
return "用户不存在";
}
if (!user.get_password().equals(oldPassword)) {
return "原密码不正确";
}
if (oldPassword.equals(newPassword)){
return "新密码与原密码一致";
}
if (!User.check_password(newPassword)) {
return "密码长6-20位至少包含大小写字母和数字";
}
user.set_password(newPassword);
if (save_users()) {
return "修改成功";
}
return "修改失败";
}
public User find_user(String email){
for (User user : users) {
if (user.get_email().equals(email)) {
return user;
}
}
return null;
}
public boolean save_users(){
File baseDir = new File(base_dir);
if (!baseDir.exists()) {
if (!baseDir.mkdirs()){
return false;
}
}
String file_path=base_dir+"用户信息.txt";
try (PrintWriter writer = new PrintWriter(new FileWriter(file_path))) {
for (int i = 0; i < users.size(); i++) {
writer.println(users.get(i).get_email()+" "+users.get(i).get_password());
if (i < users.size() - 1) {
writer.println();
}
}
return true;
} catch (IOException e) {
return false;
}
}
public boolean load_users(){
users=new ArrayList<>();
String file_path=base_dir+"用户信息.txt";
File file=new File(file_path);
if (file.exists()){
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line;
while ((line = reader.readLine()) != null) {
if (!line.trim().isEmpty()) {
String l=line.trim();
String[] parts=l.split(" ");
if (parts.length==2){
User temp=new User(parts[0]);
temp.set_password(parts[1]);
users.add(temp);
}
}
}
return true;
} catch (IOException e) {
return false;
}
}
return false;
}
}
Loading…
Cancel
Save