一、设计背景

1.需求分析

对于很多人来说拥有一副好身材能让自己增添不少魅力;对于爱吃而又担心自己发胖的人来说适当的运动健身是最好的选择。移动互联网时代,市场上“约跑”“约健身”健身APP软件成为新时代闺蜜朋友的互动模式,健身热潮的来临,这样让越来越多的人加入健身的行列中,大众的健身热情也刺激着更多与健身有关的产业飞速发展,尤其是与“互联网+”结合产生的智能健身运动App开发更是发展得如火如荼... 人们通过一款健身运动型App应用就可以随时随地的进行健身锻炼,可以不用去健身房锻炼也可以达到完美的身材,这样健身运动App开发给人们带来了极大的方便。所以这次做的是一款健身类的软件,为了方便用户随时随地可以健身。在配色方面使用白色和绿色非常简单的颜色能让人眼前一亮。在软件功能方面,用户首先需要注册用户名填写密码,注册成功之后,用户可以用之前注册的用户名和密码进行登录。登录成功之后进入到导航页面,其中包括会员信息和健身项目两个部分,会员信息记录了会员的姓名身高体重等一些基本信息,还可以查看用户报名的课程名称,可以增加以及删除报名项目,健身项目页面则是列举出一些项目名称来供用户选择。

2.目的和意义

所以这次做的是一款健身类的软件,为了方便用户随时随地可以健身。在配色方面使用白色和绿色非常简单的颜色能让人眼前一亮。在软件功能方面,用户首先需要注册用户名填写密码,注册成功之后,用户可以用之前注册的用户名和密码进行登录。登录成功之后进入到导航页面,其中包括会员信息和健身项目两个部分,会员信息记录了会员的姓名身高体重等一些基本信息,还可以查看用户报名的课程名称,可以增加以及删除报名项目,健身项目页面则是列举出一些项目名称来供用户选择。

  1. 系统需求分析与开发环境
  2. 系统功能需求
    需要包含登入注册功能,用户名和密码储存在Sharedpreferences轻型数据类中,按钮实现页面跳转。包括数据库的增删查改功能,采用的是SQLite数据库。
  3. 系统界面需求
    简介美观,采用代表健康的绿色作为主色调,和健身的主题相符合。注册和登入的页面参考了许多app,要让页面做到简介美观,所以登入注册页面都用到了自定义按钮样式和自定义输入框样式,按钮设计出颜色渐变的样式并加入圆角看起来不生硬,输入框同样加入了圆角的设计。
  4. 开发环境

Android studio3.5.0

  1. 系统设计

登入注册页面制作完后,做了一个导航页面,页面上方可以横向滑动健身馆内部的图片。然后是会员页面,用户可以通过这个页面查询自己会员信息,这个页面也加入了增删查改的功能,采用的是SQlite数据库,方便用户对课程时间的记录。页面的设计同样采用了按钮的自定义样式和输入框的自定义样式。页面上方是用户的基本信息介绍,头像部分也是设计了一个图片样式的自定义,给图片添加了一个边框,使页面看起来和谐统一美观。

最后是一个课程的展示界面,包括了健身馆开展的全部课程,方便用户查看和挑选。

  1. 系统测试
  2. 电脑模拟器测试

  1. 总结与展望
    1.总结
    在这次移动终端开发课程设计过程中,我发现平时学习的知识与实践环节所用到的有一定的差距,往往我觉得自己掌握的很好或者自认为熟练的技术却在此次实践环节中往往出问题,书本上的知识只提供方法的借鉴,实践中自己必须摸索出适合具体工作的方法,这一切都离不开钻研精神与勤学好问的精神.在人与人相处过程中我收获更大,首先要谦虚谨慎,不能自以为是,认为自己懂得很多,而仅仅埋头苦干,而不向他人请教,工作不但是实践与应用的过程,同时也是学习的过程,我们必须加强与他人的沟通学习,以便获得与他人的交流。在这短短的时间里,让我深深的感觉到自己在实际应用中所学专业知识的匮乏。让我真真领悟到“学无止境”这句话的涵义。而老师在专业认识周中所讲的,都是课本上没有而对我们又非常实用的东西,这又给我们的实训增加了浓墨淡采的光辉。我懂得了实际生活中,专业知识是怎样应用与实践的。在这些过程中,我不仅知道了职业生涯所需具备的专业知识,而且让我深深体会到一个团队中各成员合作的重要性,要善于团队合作,善于利用别人的智慧,这才是大智慧。靠单一的力量是很难完成一个大项目的,在进行团队合作的时候,还要耐心听取每个成员的意见,使我们的组合达到更加完美。
  2. 重要程序
  3. LoginActivity
    public class LoginActivity extends AppCompatActivity {
    private TextView tv_main_title;//标题
    private TextView tv_back,tv_register,tv_find_psw;//返回键,显示的注册,找回密码
    private Button btn_login;//登录按钮
    private String userName,psw,spPsw;//获取的用户名,密码,加密密码
    private EditText et_user_name,et_psw;//编辑框
    @Override
    protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    //设置此界面为竖屏
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    init();
    }
    //获取界面控件
    private void init() {
    //从main_title_bar中获取的id
    tv_main_title=findViewById(R.id.tv_main_title);
    tv_main_title.setText("登录");
    tv_back=findViewById(R.id.tv_back);
    //从activity_login.xml中获取的
    tv_register=findViewById(R.id.tv_register);
    tv_find_psw=findViewById(R.id.tv_find_psw);
    btn_login=findViewById(R.id.btn_login);
    et_user_name=findViewById(R.id.et_user_name);
    et_psw=findViewById(R.id.et_psw);
    //返回键的点击事件
    tv_back.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    //登录界面销毁
    LoginActivity.this.finish();
    }
    });
    //立即注册控件的点击事件
    tv_register.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    //为了跳转到注册界面,并实现注册功能
    Intent intent=new Intent(LoginActivity.this,RegisterActivity.class);
    startActivityForResult(intent, 1);
    }
    });
    //找回密码控件的点击事件
    tv_find_psw.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    //跳转到找回密码界面(此页面暂未创建)
    }
    });
    //登录按钮的点击事件
    btn_login.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    //开始登录,获取用户名和密码 getText().toString().trim();
    userName=et_user_name.getText().toString().trim();
    psw=et_psw.getText().toString().trim();
    //对当前用户输入的密码进行MD5加密再进行比对判断, MD5Utils.md5( ); psw 进行加密判断是否一致
    String md5Psw= MD5Utils.md5(psw);
    // md5Psw ; spPsw 为 根据从SharedPreferences中用户名读取密码
    // 定义方法 readPsw为了读取用户名,得到密码
    spPsw=readPsw(userName);
    // TextUtils.isEmpty
    if(TextUtils.isEmpty(userName)){
    Toast.makeText(LoginActivity.this"请输入用户名", Toast.LENGTH_SHORT).show();
    return;
    }else if(TextUtils.isEmpty(psw)){
    Toast.makeText(LoginActivity.this"请输入密码", Toast.LENGTH_SHORT).show();
    return;
    // md5Psw.equals(); 判断,输入的密码加密后,是否与保存在SharedPreferences中一致
    }else if(md5Psw.equals(spPsw)){
    //一致登录成功
    Toast.makeText(LoginActivity.this"登录成功", Toast.LENGTH_SHORT).show();
    //保存登录状态,在界面保存登录的用户名 定义个方法 saveLoginStatus boolean 状态 , userName 用户名;
    saveLoginStatus(trueuserName);
    //登录成功后关闭此页面进入主页
    Intent data=new Intent();
    //datad.putExtra( ); name , value ;
    data.putExtra("isLogin",true);
    //RESULT_OK为Activity系统常量,状态码为-1
    // 表示此页面下的内容操作成功将data返回到上一页面,如果是用back返回过去的则不存在用setResult传递data值
    setResult(RESULT_OK,data);
    //销毁登录界面
    LoginActivity.this.finish();
    //跳转到主界面,登录成功的状态传递到 MainActivity 中
    startActivity(new Intent(LoginActivity.this,Classification.class));
    return;
    }else if((spPsw!=null&&!TextUtils.isEmpty(spPsw)&&!md5Psw.equals(spPsw))){
    Toast.makeText(LoginActivity.this"输入的用户名和密码不一致", Toast.LENGTH_SHORT).show();
    return;
    }else{
    Toast.makeText(LoginActivity.this"此用户名不存在", Toast.LENGTH_SHORT).show();
    }
    }
    });
    }

    private String readPsw(String userName){
    //getSharedPreferences("loginInfo",MODE_PRIVATE);
    //"loginInfo",mode_private; MODE_PRIVATE表示可以继续写入
    SharedPreferences sp=getSharedPreferences("loginInfo"MODE_PRIVATE);
    //sp.getString() userName, "";
    return sp.getString(userName , "");
    }

    private void saveLoginStatus(boolean status,String userName){
    //saveLoginStatus(true, userName);
    //loginInfo表示文件名 SharedPreferences sp=getSharedPreferences("loginInfo", MODE_PRIVATE);
    SharedPreferences sp=getSharedPreferences("loginInfo"MODE_PRIVATE);
    //获取编辑器
    SharedPreferences.Editor editor=sp.edit();
    //存入boolean类型的登录状态
    editor.putBoolean("isLogin", status);
    //存入登录状态时的用户名
    editor.putString("loginUserName", userName);
    //提交修改
    editor.commit();
    }
    /**
    * 注册成功的数据返回至此
    @param requestCode 请求码
    @param resultCode 结果码
    @param data 数据
    */
    @Override
    //显示数据, onActivityResult
    //startActivityForResult(intent, 1); 从注册界面中获取数据
    //int requestCode , int resultCode , Intent data
    // LoginActivity -> startActivityForResult -> onActivityResult();
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    //super.onActivityResult(requestCode, resultCode, data);
    super.onActivityResult(requestCode, resultCode, data);
    if(data!=null){
    //是获取注册界面回传过来的用户名
    // getExtra().getString("***");
    String userName=data.getStringExtra("userName");
    if(!TextUtils.isEmpty(userName)){
    //设置用户名到 et_user_name 控件
    et_user_name.setText(userName);
    //et_user_name控件的setSelection()方法来设置光标位置
    et_user_name.setSelection(userName.length());
    }
    }
    }

    }

  4. RegisterActivity
    public class RegisterActivity extends AppCompatActivity {
    private TextView tv_main_title;//标题
    private TextView tv_back;//返回按钮
    private Button btn_register;//注册按钮
    //用户名,密码,再次输入的密码的控件
    private EditText et_user_name,et_psw,et_psw_again;
    //用户名,密码,再次输入的密码的控件的获取值
    private String userName,psw,pswAgain;
    //标题布局
    private RelativeLayout rl_title_bar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //设置页面布局 ,注册界面
    setContentView(R.layout.activity_register);
    //设置此界面为竖屏
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    init();
    }

    private void init() {
    //从main_title_bar.xml 页面布局中获取对应的UI控件
    tv_main_title=findViewById(R.id.tv_main_title);
    tv_main_title.setText("注册");
    tv_back=findViewById(R.id.tv_back);
    //布局根元素
    rl_title_bar=findViewById(R.id.title_bar);
    rl_title_bar.setBackgroundColor(Color.TRANSPARENT);
    //从activity_register.xml 页面中获取对应的UI控件
    btn_register=findViewById(R.id.btn_register);
    et_user_name=findViewById(R.id.et_user_name);
    et_psw=findViewById(R.id.et_psw);
    et_psw_again=findViewById(R.id.et_psw_again);
    tv_back.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    //返回键
    RegisterActivity.this.finish();
    }
    });
    //注册按钮
    btn_register.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
    //获取输入在相应控件中的字符串
    getEditString();
    //判断输入框内容
    if(TextUtils.isEmpty(userName)){
    Toast.makeText(RegisterActivity.this"请输入用户名", Toast.LENGTH_SHORT).show();
    return;
    }else if(TextUtils.isEmpty(psw)){
    Toast.makeText(RegisterActivity.this"请输入密码", Toast.LENGTH_SHORT).show();
    return;
    }else if(TextUtils.isEmpty(pswAgain)){
    Toast.makeText(RegisterActivity.this"请再次输入密码", Toast.LENGTH_SHORT).show();
    return;
    }else if(!psw.equals(pswAgain)){
    Toast.makeText(RegisterActivity.this"输入两次的密码不一样", Toast.LENGTH_SHORT).show();
    return;
    /**
    *从SharedPreferences中读取输入的用户名,判断SharedPreferences中是否有此用户名
    */
    }else if(isExistUserName(userName)){
    Toast.makeText(RegisterActivity.this"此账户名已经存在", Toast.LENGTH_SHORT).show();
    return;
    }else{
    Toast.makeText(RegisterActivity.this"注册成功", Toast.LENGTH_SHORT).show();
    //把账号、密码和账号标识保存到sp里面
    /**
    * 保存账号和密码到SharedPreferences中
    */
    saveRegisterInfo(userNamepsw);
    //注册成功后把账号传递到LoginActivity.java中
    // 返回值到loginActivity显示
    Intent data = new Intent();
    data.putExtra("userName"userName);
    setResult(RESULT_OK, data);
    //RESULT_OK为Activity系统常量,状态码为-1,
    // 表示此页面下的内容操作成功将data返回到上一页面,如果是用back返回过去的则不存在用setResult传递data值
    RegisterActivity.this.finish();
    }
    }
    });
    }
    /**
    * 获取控件中的字符串
    */
    private void getEditString(){
    userName=et_user_name.getText().toString().trim();
    psw=et_psw.getText().toString().trim();
    pswAgain=et_psw_again.getText().toString().trim();
    }
    /**
    * 从SharedPreferences中读取输入的用户名,判断SharedPreferences中是否有此用户名
    */
    private boolean isExistUserName(String userName){
    boolean has_userName=false;
    //mode_private SharedPreferences sp = getSharedPreferences( );
    // "loginInfo", MODE_PRIVATE
    SharedPreferences sp=getSharedPreferences("loginInfo"MODE_PRIVATE);
    //获取密码
    String spPsw=sp.getString(userName, "");//传入用户名获取密码
    //如果密码不为空则确实保存过这个用户名
    if(!TextUtils.isEmpty(spPsw)) {
    has_userName=true;
    }
    return has_userName;
    }

    private void saveRegisterInfo(String userName,String psw){
    String md5Psw = MD5Utils.md5(psw);//把密码用MD5加密
    //loginInfo表示文件名, mode_private SharedPreferences sp = getSharedPreferences( );
    SharedPreferences sp=getSharedPreferences("loginInfo"MODE_PRIVATE);
    //获取编辑器, SharedPreferences.Editor editor -> sp.edit();
    SharedPreferences.Editor editor=sp.edit();
    //以用户名为key,密码为value保存在SharedPreferences中
    //key,value,如键值对,editor.putString(用户名,密码);
    editor.putString(userName, md5Psw);
    //提交修改 editor.commit();
    editor.commit();
    }
    }

  5. DatabaseHelper

public class DatabaseHelper extends SQLiteOpenHelper {

public DatabaseHelper(Context context){super(context,"Test.db",null,1);}
//第一个参数是上下文,第二个参数是数据库名称,
//第三个参数是CursorFactory对象,一般设置为null,第四个参数是数据库的版本
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE information(_id INTEGER PRIMARY KEY AUTOINCREMENT,name VARCHAR(20),age INTEGER)");
}
//创建表 表名information 表结构 自增id,字符串姓名,int年龄

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.d("myDeBug","数据库版本已更新");
}
//数据库版本发生变化时调用
}

4.DictActivity

public class DictActivity extends AppCompatActivity {
private Button insertButtonupdateButtonsearchButtondeleteButton;
private Button btn_xl1;
private EditText nameage;
private TextView showshowAge;
final DatabaseHelper dbHelper new DatabaseHelper(DictActivity.this);

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dict);

btn_xl1 = findViewById(R.id.btn_xl);
btn_xl1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//创建Intent 对象
Intent intent = new Intent(DictActivity.this, Classification.class);
//启动Activity
startActivity(intent);
}
});

insertButton = findViewById(R.id.btn_insert);
updateButton = findViewById(R.id.btn_update);
searchButton = findViewById(R.id.btn_search);
deleteButton = findViewById(R.id.btn_delete);
name = findViewById(R.id.name);
age = findViewById(R.id.age);
show = findViewById(R.id.tv_show);
showAge = findViewById(R.id.tv_showAge);

SQLiteDatabase db = dbHelper.getReadableDatabase();

myShow();

insertButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("name"name.getText().toString());
values.put("age"age.getText().toString());
long id = db.insert("information"null, values);
Log.d("myDeBug""insert");

myShow();

db.close();
name.setText(null);
age.setText(null);
}
});
updateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("age"age.getText().toString());
db.update("information", values, "name=?"new String[]{name.getText().toString()});

myShow();

db.close();
Log.d("myDebug""update");
name.setText(null);
age.setText(null);
}
});
searchButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

SQLiteDatabase db = dbHelper.getWritableDatabase();
String name1 = name.getText().toString();
show.setText(null);
if (name1.equals("")) {
myShow();

db.close();
else {
show.setText("项目名称");
showAge.setText("日期");
Cursor cursor = db.rawQuery("select * from information where name = ? "new String[]{name1});

while (cursor.moveToNext()) {
String newName = cursor.getString(cursor.getColumnIndex("name"));
int newAge = cursor.getInt(cursor.getColumnIndex("age"));
// show.setText(show.getText() + "\n" + newName + "\t" + newAge);
show.setText(show.getText() + "\n" + newName);
showAge.setText(showAge.getText() + "\n" + newAge);
}

cursor.close();
db.close();
name.setText(null);
age.setText(null);
}
}
});
deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete("information""name=?"new String[]{name.getText().toString()});

myShow();

db.close();
Log.d("myDeBug""DeleteSuccess");
name.setText(null);
age.setText(null);
}
});

}

public void myShow() {
SQLiteDatabase db = dbHelper.getReadableDatabase();

show.setText("项目名称");
showAge.setText("日期");
Cursor cursor = db.rawQuery("select * from information"null);

while (cursor.moveToNext()) {
String newName = cursor.getString(cursor.getColumnIndex("name"));
int newAge = cursor.getInt(cursor.getColumnIndex("age"));
show.setText(show.getText() + "\n" + newName);
showAge.setText(showAge.getText() + "\n" + newAge);
}
cursor.close();
}
}

安卓APP源码和设计报告——健身系统相关推荐

  1. 安卓APP源码和设计报告——体重档案APP(含答辩PPT)

    移动媒体程序设计实现课程设计报告 课题名称:体重档案APP小组 小组成员:xxx xxx xxx 摘要: Window 操作系统的诞生成就了微软帝国,同时也造就了 PC 时代的繁荣, 然而如今,以 A ...

  2. 安卓APP源码和设计报告——个人通讯录

    摘 要 随着移动设备制造技术和移动通信网络的迅猛发展,全球手机用户日益增加,手机成为了很多人日常生活中必不可少的一部分,手机业在日益发展的同时,人们对手机的功能需求和体验需求也越来越高,因此各种智能手 ...

  3. 安卓APP源码和设计报告——智能垃圾桶

    课程名称: 移动互联网应用开发 实验名称: 姓名/学号: 专业/班级: 指导教师: 实验时间: 一.案例功能需求 该系统是了解垃圾分类以及物品查询属于哪类垃圾的智能化APP.该系统可以实现用户登陆注册 ...

  4. 安卓APP源码和设计报告——运动健身教学

    实 验 报 告 课程名称 实验名称 指导教师 专业 班级 学号 姓名 目 录 一.设计背景31. 需求分析32. 课题研究的目的和意义3二.系统需求分析与开发环境31. 系统功能需求32.系统界面需求 ...

  5. 安卓APP源码和设计报告——基于Android的垃圾分类系统

    <移动应用开发>大作业报告 题 目    基于Android的垃圾分类系统 系 部     班 级     学 生 姓 名     学 号     指 导 教 师     时 间     ...

  6. 安卓APP源码和设计报告——快递查询录入系统

    <多媒体通信技术> 题 目: 快递 完 成 日 期 2022年05月 目 录 1 绪论1 2 设计方案2 2.1 设计思路和方案2 2.2 功能要求2 2.3 设计的流程图2 3 设计过程 ...

  7. 安卓APP源码和设计报告——手机天气预报系统

    目录 摘要1需求分析2一.开发背景2二.项目需求分析2总体设计2一.系统规划2二.系统功能界面3设置预报城市界面:3天气显示界面:4Widget 桌面小部件界面:5三.设计目标6系统设计6一.开发及运 ...

  8. 安卓app源码和设计报告——简易记账本

    课 程 设 计(实训)说 明 书 题目 实现简易记账本功能 专 业 班 级 学生姓名 同组学生 指导老师 课程设计(实训)评语 学生姓名 专业 班级 2 题目 实现简易记账本功能 评语: 成绩: 优 ...

  9. 安卓APP源码和设计报告——仿淘宝购物APP

    2021-2022学年第二学期期末考试 <Android手机软件开发>实践考核 项目设计说明书 项目名称: 购物APP的设计与实现 专 业: 计算机科学与技术 学 号: 姓 名: 任课教师 ...

最新文章

  1. 小程序在wxml使用indexOf
  2. 通过产品ID得到collection!!!
  3. day02 文件读写
  4. Neutron — VLAN aware VMs 与 VLAN transparent
  5. Tomcat 配置安装
  6. css实现左边div固定宽度,右边div自适应撑满剩下的宽度
  7. 为什么中国的程序员技术偏低
  8. 指令和伪指令和宏指令区别
  9. 区块链教程Fabric1.0源代码分析流言算法Gossip服务端二
  10. extjs combobox下拉框显示位置问题
  11. python列表字典元祖_python列表,字典,元组常用方法和集合
  12. 全网首发:ProGuard保持一个类名函数名需要加public
  13. FreeSwitch 相关资料
  14. 计算机继续教育笔记,第三轮继续教育自学读书笔记
  15. poj2528 贴海报
  16. 二叉平衡树的算法复杂度笔记
  17. [译] 如果界面产品设计师设计实体产品
  18. 图像处理问题解决师——求取每个颗粒到其他颗粒边缘的最近距离
  19. 有关嵌入式硬件测试的资料
  20. 全球及中国邮件营销服务行业发展趋势及投资策略分析报告2022-2028年

热门文章

  1. 3d渲染时显示计算机渲染过程,【技巧分享】如何解决3d渲染时出现错误
  2. kali 安全/运维 开源教程2022
  3. 黑鹰s耳机可以听到自己的声音
  4. Shell文件查找之find命令(2)
  5. 2007MTV超级盛典详细介绍
  6. Hystrix的原理及使用
  7. 90%的交互设计师都知道的坑,程序员还在做吗?
  8. jq js100vh做减法算法
  9. 从百度文库下载的文档无法打开解决办法
  10. Incorrect string value: ‘\xE6\x9D\x8E\xE8\x80\x81...‘ for column ‘name‘ at row 1