python-mysql期末实验:四、数据导入界面的制作

本专栏目录:

一、实验综述

二、基于MySQL进行的数据库的搭建

三、程序登录、注册界面的制作

四、数据导入界面的制作(即本篇)

五、collage(大学)表的增删改查界面的制作

六、province(省份)表的增删改查界面的制作

七、student_num(考生人数)表的增删改查界面以及数据可视化的制作

八、min_score_line(最低分数线)表的增删改查界面以及数据可视化的制作

九、collage_level(学校等级)表的增删改查界面的制作

十、enrollment_type(招生类型)表的增删改查界面的制作

十一、enrollment(招生人数)表的增删改查界面以及数据可视化的制作

十二、school_type(学校类型)表的增删改查界面的制作

十三、collage_school_level(各高校等级)表的增删改查界面的制作

十四、collage_province_enrollment_type(各高校招生类型)表的增删改查界面的制作

如果需要整个代码文件,以及数据库中的数据,或者有较为复杂的问题,请添加QQ:3095631599(CSDN-山河之书),添加时请备注:CSDN。

本部分将叙述数据导入界面函数(即本专栏第三篇文章中的load_data_choose函数)及其下属界面的制作过程

这部分总共包括十一个界面:导入表格选择界面以及下属的十张表的导入界面

可以实现的功能包括:支持对除账户表格外其他表格进行选择,并进入具体表格数据导入界面,支持导入文件的路径格式合法性检查、路径存在性检查,支持数据批量导入。

接下来将舞台交给代码段,所有的解释都将以注释的形式呈现:

import tkinter as tk  # 本代码段需用
import pymysql as py  # 本代码段需用
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from tkinter import ttk
from tkinter import messagebox  # 本代码段需用
import re  # 本代码段需用
import turtle
import random
import time


# 导入数据表格选择函数
def load_data_choose():  # 有一说一,load_data_choose函数的搭建和上一篇文章中choose函数的搭建不能说是一模一样,只能说是异曲同工,逻辑完全一样因此也不必多解释,可以回去看原来的
    window_load_data_choose = tk.Tk()
    window_load_data_choose.title("表格选择")
    window_load_data_choose.geometry("450x300")
    tk.Label(window_load_data_choose, text="高校报考信息批量导入系统").place(x=160, y=0)
    tk.Label(window_load_data_choose, text="请选择表格").place(x=190, y=20)
    collage = tk.Button(window_load_data_choose, text="大学", command=load_data_collage_use)
    collage.place(x=0, y=50)
    province = tk.Button(window_load_data_choose, text="省份", command=load_data_province_use)
    province.place(x=0, y=80)
    student_num = tk.Button(window_load_data_choose, text="考生人数", command=load_data_student_num_use)
    student_num.place(x=0, y=110)
    min_score_line = tk.Button(window_load_data_choose, text="最低分数线", command=load_data_min_score_line_use)
    min_score_line.place(x=0, y=140)
    school_level = tk.Button(window_load_data_choose, text="学校等级", command=load_data_school_level_use)
    school_level.place(x=0, y=170)
    enrollment_type = tk.Button(window_load_data_choose, text="招生类型", command=load_data_enrollment_type_use)
    enrollment_type.place(x=225, y=50)
    enrollment = tk.Button(window_load_data_choose, text="招生人数", command=load_data_enrollment_use)
    enrollment.place(x=225, y=80)
    school_type = tk.Button(window_load_data_choose, text="学校类型", command=load_data_school_type_use)
    school_type.place(x=225, y=110)
    collage_school_level = tk.Button(window_load_data_choose, text="各高校等级",
                                     command=load_data_collage_school_level_use)
    collage_school_level.place(x=225, y=140)
    collage_province_enrollment_type = tk.Button(window_load_data_choose, text="各高校招生类型",
                                                 command=load_data_collage_province_enrollment_type_use)
    collage_province_enrollment_type.place(x=225, y=170)

    # 返回函数
    def quit_window_load_data_choose():
        window_load_data_choose.destroy()
    quit_window_load_data_choose = tk.Button(window_load_data_choose, text="返回", command=quit_window_load_data_choose)
    quit_window_load_data_choose.place(x=280, y=230)


# collage 表导入—————————————————————————————————————————————————————————————————————————————————————————————————————————
# 对于每一张表,导入的流程都是完全一样的,均采用识别文档路径,打开文档,利用SQL语句导入数据的形式
def load_data_collage_use():
    window_load_data = tk.Tk()
    window_load_data.title("大学表数据插入操作界面")
    window_load_data.geometry("450x300")

    path = tk.Label(window_load_data, text="请输入txt文档路径")  # 也可以用csv文件(csv其实更好),但后面的SQL语句要作相应修改,具体可以查一下csv文件导入数据库的SQL语句
    path.grid(row=2, column=0)
    path_str = tk.StringVar()
    path_input = tk.Entry(window_load_data, width=20, textvariable=path_str)
    path_input.grid(row=2, column=1)  # 路径的输入框,原谅我不知道如何直接对接“此电脑”,然后搞一个路径选择界面出来

    def load_in_use():
        path_info = path_input.get()  # 获取输入的路径
        pattern_path = r"^.+\.(txt)$"  # 路径格式合法性验证的正则表达式,表达的意思是xxx.txt
        result_path = re.match(pattern_path, path_info)  # 路径格式校验
        try:
            if not result_path:
                tk.messagebox.showerror("错误", "请输入txt文件路径")  # 路径错误提示
            else:  # 如果满足格式的话就连接数据库开始导入
                try:
                    conn = py.connect(host='%s' % ip, user='lzx', password='lzx', port=3306, database='dbms_report',
                                      charset='utf8')
                    cursor = conn.cursor()
                    cursor.execute("SET FOREIGN_KEY_CHECKS=0;")  # 停用参照完整性约束,便于数据导入修改
                    conn.commit()
                    cursor.execute("load data infile '%d' into table collage;" % path_info)  # 导入数据
                    cursor.execute("update dbms_report.collage set \
                    school_type_name=substring(school_type_name,1,length(school_type_name)-1);")  # 数据清洗,如果用csv文件的话就没有这一步,也没有上上步和下一步,只有导入数据那一步
                    cursor.execute("SET FOREIGN_KEY_CHECKS=1;")  # 恢复外键(参照完整性约束)
                    conn.commit()
                    conn.close()
                except py.err.IntegrityError:
                    tk.messagebox.showerror("错误", "路径问题、违反外键问题或数据存在重复")  # 对数据错误进行警示,比如数据违反了完整性约束,或者数据长度超乎容纳力,或者路径压根不存在,都会报错
        except ValueError:
            tk.messagebox.showerror("数据类型有问题")  # 导入数据时发现导入的数据类型上有问题,直接报错

    load_in = tk.Button(window_load_data, text="导入", command=load_in_use)
    load_in.grid(row=3, column=0)  # 设置导入键

    # 返回函数
    def quit_window_load_data():
        window_load_data.destroy()
    quit_window_load_data = tk.Button(window_load_data, text="返回", command=quit_window_load_data)
    quit_window_load_data.grid(row=3, column=2)


# 一概同上
# province 表导入————————————————————————————————————————————————————————————————————————————————————————————————————————
def load_data_province_use():
    window_load_data = tk.Tk()
    window_load_data.title("省份表数据插入操作界面")
    window_load_data.geometry("450x300")

    path = tk.Label(window_load_data, text="请输入txt文档路径")
    path.grid(row=2, column=0)
    path_str = tk.StringVar()
    path_input = tk.Entry(window_load_data, width=20, textvariable=path_str)
    path_input.grid(row=2, column=1)

    def load_in_use():
        path_info = path_input.get()
        pattern_path = r"^.+\.(txt)$"
        result_path = re.match(pattern_path, path_info)
        try:
            if not result_path:
                tk.messagebox.showerror("错误", "请输入txt文件路径")
            else:
                try:
                    conn = py.connect(host='%s' % ip, user='lzx', password='lzx', port=3306, database='dbms_report',
                                      charset='utf8')
                    cursor = conn.cursor()
                    cursor.execute("SET FOREIGN_KEY_CHECKS=0;")
                    conn.commit()
                    cursor.execute("load data infile '%d' into table province;" % path_info)
                    cursor.execute("update dbms_report.province set \
                    PEAEI_URL=substring(PEAEI_URL,1,length(PEAEI_URL)-1);")
                    cursor.execute("SET FOREIGN_KEY_CHECKS=1;")
                    conn.commit()
                    conn.close()
                except py.err.IntegrityError:
                    tk.messagebox.showerror("错误", "路径问题、违反外键问题或数据存在重复")
        except ValueError:
            tk.messagebox.showerror("数据类型有问题")

    load_in = tk.Button(window_load_data, text="导入", command=load_in_use)
    load_in.grid(row=3, column=0)

    # 返回函数
    def quit_window_load_data():
        window_load_data.destroy()
    quit_window_load_data = tk.Button(window_load_data, text="返回", command=quit_window_load_data)
    quit_window_load_data.grid(row=3, column=2)


# student_num 表导入—————————————————————————————————————————————————————————————————————————————————————————————————————
def load_data_student_num_use():
    window_load_data = tk.Tk()
    window_load_data.title("省份表数据插入操作界面")
    window_load_data.geometry("450x300")

    path = tk.Label(window_load_data, text="请输入txt文档路径")
    path.grid(row=2, column=0)
    path_str = tk.StringVar()
    path_input = tk.Entry(window_load_data, width=20, textvariable=path_str)
    path_input.grid(row=2, column=1)

    def load_in_use():
        path_info = path_input.get()
        pattern_path = r"^.+\.(txt)$"
        result_path = re.match(pattern_path, path_info)
        try:
            if not result_path:
                tk.messagebox.showerror("错误", "请输入txt文件路径")
            else:
                try:
                    conn = py.connect(host='%s' % ip, user='lzx', password='lzx', port=3306, database='dbms_report',
                                      charset='utf8')
                    cursor = conn.cursor()
                    cursor.execute("SET FOREIGN_KEY_CHECKS=0;")
                    conn.commit()
                    cursor.execute("load data infile '%d' into table student_num;" % path_info)
                    cursor.execute("update dbms_report.student_num set \
                    student_in_total=substring(student_in_total,1,length(student_in_total)-1);")
                    cursor.execute("SET FOREIGN_KEY_CHECKS=1;")
                    conn.commit()
                    conn.close()
                except py.err.IntegrityError:
                    tk.messagebox.showerror("错误", "路径问题、违反外键问题或数据存在重复")
        except ValueError:
            tk.messagebox.showerror("数据类型有问题")

    load_in = tk.Button(window_load_data, text="导入", command=load_in_use)
    load_in.grid(row=3, column=0)

    # 返回函数
    def quit_window_load_data():
        window_load_data.destroy()
    quit_window_load_data = tk.Button(window_load_data, text="返回", command=quit_window_load_data)
    quit_window_load_data.grid(row=3, column=2)


# min_score_line 表导入——————————————————————————————————————————————————————————————————————————————————————————————————
def load_data_min_score_line_use():
    window_load_data = tk.Tk()
    window_load_data.title("省份表数据插入操作界面")
    window_load_data.geometry("450x300")

    path = tk.Label(window_load_data, text="请输入txt文档路径")
    path.grid(row=2, column=0)
    path_str = tk.StringVar()
    path_input = tk.Entry(window_load_data, width=20, textvariable=path_str)
    path_input.grid(row=2, column=1)

    def load_in_use():
        path_info = path_input.get()
        pattern_path = r"^.+\.(txt)$"
        result_path = re.match(pattern_path, path_info)
        try:
            if not result_path:
                tk.messagebox.showerror("错误", "请输入txt文件路径")
            else:
                try:
                    conn = py.connect(host='%s' % ip, user='lzx', password='lzx', port=3306, database='dbms_report',
                                      charset='utf8')
                    cursor = conn.cursor()
                    cursor.execute("SET FOREIGN_KEY_CHECKS=0;")
                    conn.commit()
                    cursor.execute("load data infile '%d' into table min_score_line;" % path_info)
                    cursor.execute("update dbms_report.min_score_line set \
                    min_score=substring(min_score,1,length(min_score)-1);")
                    cursor.execute("SET FOREIGN_KEY_CHECKS=1;")
                    conn.commit()
                    conn.close()
                except py.err.IntegrityError:
                    tk.messagebox.showerror("错误", "路径问题、违反外键问题或数据存在重复")
        except ValueError:
            tk.messagebox.showerror("数据类型有问题")

    load_in = tk.Button(window_load_data, text="导入", command=load_in_use)
    load_in.grid(row=3, column=0)

    # 返回函数
    def quit_window_load_data():
        window_load_data.destroy()

    quit_window_load_data = tk.Button(window_load_data, text="返回", command=quit_window_load_data)
    quit_window_load_data.grid(row=3, column=2)


# school_level 表导入————————————————————————————————————————————————————————————————————————————————————————————————————
def load_data_school_level_use():
    window_load_data = tk.Tk()
    window_load_data.title("省份表数据插入操作界面")
    window_load_data.geometry("450x300")

    path = tk.Label(window_load_data, text="请输入txt文档路径")
    path.grid(row=2, column=0)
    path_str = tk.StringVar()
    path_input = tk.Entry(window_load_data, width=20, textvariable=path_str)
    path_input.grid(row=2, column=1)

    def load_in_use():
        path_info = path_input.get()
        pattern_path = r"^.+\.(txt)$"
        result_path = re.match(pattern_path, path_info)
        try:
            if not result_path:
                tk.messagebox.showerror("错误", "请输入txt文件路径")
            else:
                try:
                    conn = py.connect(host='%s' % ip, user='lzx', password='lzx', port=3306, database='dbms_report',
                                      charset='utf8')
                    cursor = conn.cursor()
                    cursor.execute("SET FOREIGN_KEY_CHECKS=0;")
                    conn.commit()
                    cursor.execute("load data infile '%d' into table school_level;" % path_info)
                    cursor.execute("update dbms_report.school_level set \
                    school_level_intro=substring(school_level_intro,1,length(school_level_intro)-1);")
                    cursor.execute("SET FOREIGN_KEY_CHECKS=1;")
                    conn.commit()
                    conn.close()
                except py.err.IntegrityError:
                    tk.messagebox.showerror("错误", "路径问题、违反外键问题或数据存在重复")
        except ValueError:
            tk.messagebox.showerror("数据类型有问题")

    load_in = tk.Button(window_load_data, text="导入", command=load_in_use)
    load_in.grid(row=3, column=0)

    # 返回函数
    def quit_window_load_data():
        window_load_data.destroy()

    quit_window_load_data = tk.Button(window_load_data, text="返回", command=quit_window_load_data)
    quit_window_load_data.grid(row=3, column=2)


# enrollment_type 表导入—————————————————————————————————————————————————————————————————————————————————————————————————
def load_data_enrollment_type_use():
    window_load_data = tk.Tk()
    window_load_data.title("省份表数据插入操作界面")
    window_load_data.geometry("450x300")

    path = tk.Label(window_load_data, text="请输入txt文档路径")
    path.grid(row=2, column=0)
    path_str = tk.StringVar()
    path_input = tk.Entry(window_load_data, width=20, textvariable=path_str)
    path_input.grid(row=2, column=1)

    def load_in_use():
        path_info = path_input.get()
        pattern_path = r"^.+\.(txt)$"
        result_path = re.match(pattern_path, path_info)
        try:
            if not result_path:
                tk.messagebox.showerror("错误", "请输入txt文件路径")
            else:
                try:
                    conn = py.connect(host='%s' % ip, user='lzx', password='lzx', port=3306, database='dbms_report',
                                      charset='utf8')
                    cursor = conn.cursor()
                    cursor.execute("SET FOREIGN_KEY_CHECKS=0;")
                    conn.commit()
                    cursor.execute("load data infile '%d' into table enrollment_type;" % path_info)
                    cursor.execute("update dbms_report.enrollment_type set \
                    enrollment_type_intro=substring(enrollment_type_intro,1,length(enrollment_type_intro)-1);")
                    cursor.execute("SET FOREIGN_KEY_CHECKS=1;")
                    conn.commit()
                    conn.close()
                except py.err.IntegrityError:
                    tk.messagebox.showerror("错误", "路径问题、违反外键问题或数据存在重复")
        except ValueError:
            tk.messagebox.showerror("数据类型有问题")

    load_in = tk.Button(window_load_data, text="导入", command=load_in_use)
    load_in.grid(row=3, column=0)

    # 返回函数
    def quit_window_load_data():
        window_load_data.destroy()

    quit_window_load_data = tk.Button(window_load_data, text="返回", command=quit_window_load_data)
    quit_window_load_data.grid(row=3, column=2)


# enrollment 表导入——————————————————————————————————————————————————————————————————————————————————————————————————————
def load_data_enrollment_use():
    window_load_data = tk.Tk()
    window_load_data.title("省份表数据插入操作界面")
    window_load_data.geometry("450x300")

    path = tk.Label(window_load_data, text="请输入txt文档路径")
    path.grid(row=2, column=0)
    path_str = tk.StringVar()
    path_input = tk.Entry(window_load_data, width=20, textvariable=path_str)
    path_input.grid(row=2, column=1)

    def load_in_use():
        path_info = path_input.get()
        pattern_path = r"^.+\.(txt)$"
        result_path = re.match(pattern_path, path_info)
        try:
            if not result_path:
                tk.messagebox.showerror("错误", "请输入txt文件路径")
            else:
                try:
                    conn = py.connect(host='%s' % ip, user='lzx', password='lzx', port=3306, database='dbms_report',
                                      charset='utf8')
                    cursor = conn.cursor()
                    cursor.execute("SET FOREIGN_KEY_CHECKS=0;")
                    conn.commit()
                    cursor.execute("load data infile '%d' into table enrollment;" % path_info)
                    cursor.execute("update dbms_report.enrollment set \
                    enrollment_in_total=substring(enrollment_in_total,1,length(enrollment_in_total)-1);")
                    cursor.execute("SET FOREIGN_KEY_CHECKS=1;")
                    conn.commit()
                    conn.close()
                except py.err.IntegrityError:
                    tk.messagebox.showerror("错误", "路径问题、违反外键问题或数据存在重复")
        except ValueError:
            tk.messagebox.showerror("数据类型有问题")

    load_in = tk.Button(window_load_data, text="导入", command=load_in_use)
    load_in.grid(row=3, column=0)

    # 返回函数
    def quit_window_load_data():
        window_load_data.destroy()

    quit_window_load_data = tk.Button(window_load_data, text="返回", command=quit_window_load_data)
    quit_window_load_data.grid(row=3, column=2)


# school_type 表导入—————————————————————————————————————————————————————————————————————————————————————————————————————
def load_data_school_type_use():
    window_load_data = tk.Tk()
    window_load_data.title("省份表数据插入操作界面")
    window_load_data.geometry("450x300")

    path = tk.Label(window_load_data, text="请输入txt文档路径")
    path.grid(row=2, column=0)
    path_str = tk.StringVar()
    path_input = tk.Entry(window_load_data, width=20, textvariable=path_str)
    path_input.grid(row=2, column=1)

    def load_in_use():
        path_info = path_input.get()
        pattern_path = r"^.+\.(txt)$"
        result_path = re.match(pattern_path, path_info)
        try:
            if not result_path:
                tk.messagebox.showerror("错误", "请输入txt文件路径")
            else:
                try:
                    conn = py.connect(host='%s' % ip, user='lzx', password='lzx', port=3306, database='dbms_report',
                                      charset='utf8')
                    cursor = conn.cursor()
                    cursor.execute("SET FOREIGN_KEY_CHECKS=0;")
                    conn.commit()
                    cursor.execute("load data infile '%d' into table school_type;" % path_info)
                    cursor.execute("update dbms_report.school_type set \
                    school_type_intro=substring(school_type_intro,1,length(school_type_intro)-1);")
                    cursor.execute("SET FOREIGN_KEY_CHECKS=1;")
                    conn.commit()
                    conn.close()
                except py.err.IntegrityError:
                    tk.messagebox.showerror("错误", "路径问题、违反外键问题或数据存在重复")
        except ValueError:
            tk.messagebox.showerror("数据类型有问题")

    load_in = tk.Button(window_load_data, text="导入", command=load_in_use)
    load_in.grid(row=3, column=0)

    # 返回函数
    def quit_window_load_data():
        window_load_data.destroy()

    quit_window_load_data = tk.Button(window_load_data, text="返回", command=quit_window_load_data)
    quit_window_load_data.grid(row=3, column=2)


# collage_school_level 表导入————————————————————————————————————————————————————————————————————————————————————————————
def load_data_collage_school_level_use():
    window_load_data = tk.Tk()
    window_load_data.title("省份表数据插入操作界面")
    window_load_data.geometry("450x300")

    path = tk.Label(window_load_data, text="请输入txt文档路径")
    path.grid(row=2, column=0)
    path_str = tk.StringVar()
    path_input = tk.Entry(window_load_data, width=20, textvariable=path_str)
    path_input.grid(row=2, column=1)

    def load_in_use():
        path_info = path_input.get()
        pattern_path = r"^.+\.(txt)$"
        result_path = re.match(pattern_path, path_info)
        try:
            if not result_path:
                tk.messagebox.showerror("错误", "请输入txt文件路径")
            else:
                try:
                    conn = py.connect(host='%s' % ip, user='lzx', password='lzx', port=3306, database='dbms_report',
                                      charset='utf8')
                    cursor = conn.cursor()
                    cursor.execute("SET FOREIGN_KEY_CHECKS=0;")
                    conn.commit()
                    cursor.execute("load data infile '%d' into table collage_school_level;" % path_info)
                    cursor.execute("update dbms_report.collage_school_level set \
                    school_level_name=substring(school_level_name,1,length(school_level_name)-1);")
                    cursor.execute("SET FOREIGN_KEY_CHECKS=1;")
                    conn.commit()
                    conn.close()
                except py.err.IntegrityError:
                    tk.messagebox.showerror("错误", "路径问题、违反外键问题或数据存在重复")
        except ValueError:
            tk.messagebox.showerror("数据类型有问题")

    load_in = tk.Button(window_load_data, text="导入", command=load_in_use)
    load_in.grid(row=3, column=0)

    # 返回函数
    def quit_window_load_data():
        window_load_data.destroy()

    quit_window_load_data = tk.Button(window_load_data, text="返回", command=quit_window_load_data)
    quit_window_load_data.grid(row=3, column=2)


# collage_province_enrollment_type 表导入————————————————————————————————————————————————————————————————————————————————
def load_data_collage_province_enrollment_type_use():
    window_load_data = tk.Tk()
    window_load_data.title("省份表数据插入操作界面")
    window_load_data.geometry("450x300")

    path = tk.Label(window_load_data, text="请输入txt文档路径")
    path.grid(row=2, column=0)
    path_str = tk.StringVar()
    path_input = tk.Entry(window_load_data, width=20, textvariable=path_str)
    path_input.grid(row=2, column=1)

    def load_in_use():
        path_info = path_input.get()
        pattern_path = r"^.+\.(txt)$"
        result_path = re.match(pattern_path, path_info)
        try:
            if not result_path:
                tk.messagebox.showerror("错误", "请输入txt文件路径")
            else:
                try:
                    conn = py.connect(host='%s' % ip, user='lzx', password='lzx', port=3306, database='dbms_report',
                                      charset='utf8')
                    cursor = conn.cursor()
                    cursor.execute("SET FOREIGN_KEY_CHECKS=0;")
                    conn.commit()
                    cursor.execute("load data infile '%d' into table collage_province_enrollment_type;" % path_info)
                    cursor.execute("update dbms_report.collage_province_enrollment_type set \
                    enrollment_type_name=substring(enrollment_type_name,1,length(enrollment_type_name)-1);")
                    cursor.execute("SET FOREIGN_KEY_CHECKS=1;")
                    conn.commit()
                    conn.close()
                except py.err.IntegrityError:
                    tk.messagebox.showerror("错误", "路径问题、违反外键问题或数据存在重复")
        except ValueError:
            tk.messagebox.showerror("数据类型有问题")

    load_in = tk.Button(window_load_data, text="导入", command=load_in_use)
    load_in.grid(row=3, column=0)

    # 返回函数
    def quit_window_load_data():
        window_load_data.destroy()

    quit_window_load_data = tk.Button(window_load_data, text="返回", command=quit_window_load_data)
    quit_window_load_data.grid(row=3, column=2)

喜闻乐见的运行截图:

python-mysql期末实验:四、数据导入界面的制作_第1张图片

 python-mysql期末实验:四、数据导入界面的制作_第2张图片

 python-mysql期末实验:四、数据导入界面的制作_第3张图片

由于本人手中目前没有另外的数据,因此也暂时没有导入数据的具体截图,但是之前试用的时候还是可以用的。

实在是懒得另找数据了,如确有需要请直接联系本人,本人再准备数据进行测试 。

你可能感兴趣的:(python,mysql)