/** 未做测试,没有做等用-1表示的内容 */ | /** 未做测试,没有做等用-1表示的内容 */ | ||||
const val NOT_DOING = -1.0 | const val NOT_DOING = -1.0 | ||||
const val DOING_OVER = 100.0 | |||||
/** 测试通过:>80 < 90 继续加油 <80 悲伤 */ | /** 测试通过:>80 < 90 继续加油 <80 悲伤 */ | ||||
const val TEST_SCORE_LEVEL_1 = 80 | const val TEST_SCORE_LEVEL_1 = 80 |
package com.xkl.cdl.data.bean | package com.xkl.cdl.data.bean | ||||
import androidx.annotation.ColorRes | |||||
import com.xkl.cdl.R | import com.xkl.cdl.R | ||||
import java.io.Serializable | import java.io.Serializable | ||||
var repeatNum: Int = 0 | var repeatNum: Int = 0 | ||||
/**显示颜色*/ | /**显示颜色*/ | ||||
var showColor: Int = 0 | |||||
@ColorRes | |||||
var showColor:Int = 0 | |||||
get() { | get() { | ||||
return when (repeatNum) { | return when (repeatNum) { | ||||
0 -> R.color.num0 | 0 -> R.color.num0 |
learnProgress == 0.0 -> view.resources.getString(R.string.start) | learnProgress == 0.0 -> view.resources.getString(R.string.start) | ||||
learnProgress < 0.1 -> "0.1%" | learnProgress < 0.1 -> "0.1%" | ||||
learnProgress < 100 -> { | learnProgress < 100 -> { | ||||
DecimalFormat("#.#%").apply { | |||||
DecimalFormat("#.##").apply { | |||||
roundingMode = RoundingMode.DOWN | roundingMode = RoundingMode.DOWN | ||||
}.format(BigDecimal(learnProgress)) | |||||
}.format(learnProgress) + "%" | |||||
} | } | ||||
else -> "100%" | else -> "100%" | ||||
} | } |
val mSortInfoList = hashMapOf<Int, MutableList<AppApi.CourseSortedInfo.Builder>>() | val mSortInfoList = hashMapOf<Int, MutableList<AppApi.CourseSortedInfo.Builder>>() | ||||
/** | |||||
* 获取对应项目的课程数量 | |||||
* @param subjectId Int 项目 | |||||
* @return Int 课程数量 | |||||
*/ | |||||
fun getSubjectForCourseSize(subjectId : Int) : Int { | |||||
return subjectWithCoursePackMap[subjectId]?.let { | |||||
var count = 0 | |||||
it.forEach { coursePack -> | |||||
count += coursePack.childrenCourses?.size ?: 0 | |||||
} | |||||
count | |||||
} ?: 0 | |||||
} | |||||
/** | /** | ||||
* 搜索项目下的课程包 | * 搜索项目下的课程包 | ||||
* @param subjectId Int 项目id | * @param subjectId Int 项目id | ||||
return when { | return when { | ||||
progress == 0.0 -> "0" | progress == 0.0 -> "0" | ||||
progress < 0.1 -> "0.1" | progress < 0.1 -> "0.1" | ||||
progress < 100 -> DecimalFormat("#.#").apply { | |||||
progress < 100 -> DecimalFormat("#.##").apply { | |||||
//直接舍弃 | //直接舍弃 | ||||
roundingMode = RoundingMode.DOWN | roundingMode = RoundingMode.DOWN | ||||
}.format(BigDecimal(progress)) | }.format(BigDecimal(progress)) | ||||
if (totalProgress == 0.0 ) return totalProgress | if (totalProgress == 0.0 ) return totalProgress | ||||
var totalCourseSize = 0 | |||||
subjectWithCoursePackMap.get(subjectId)?.forEach { | |||||
totalCourseSize += it.childrenCourses.size | |||||
} | |||||
val totalCourseSize = getSubjectForCourseSize(subjectId) | |||||
if (totalCourseSize == 0) return 0.0 | if (totalCourseSize == 0) return 0.0 | ||||
return totalProgress / totalCourseSize | return totalProgress / totalCourseSize | ||||
} | } | ||||
if (totalProgress == 0.0 ) return totalProgress | if (totalProgress == 0.0 ) return totalProgress | ||||
var totalCourseSize = 0 | |||||
subjectWithCoursePackMap.get(subjectId)?.forEach { | |||||
totalCourseSize += it.childrenCourses.size | |||||
} | |||||
val totalCourseSize = getSubjectForCourseSize(subjectId) | |||||
if (totalCourseSize == 0) return 0.0 | if (totalCourseSize == 0) return 0.0 | ||||
return totalProgress / totalCourseSize | return totalProgress / totalCourseSize | ||||
} | } | ||||
/** | |||||
* 获取对应项目的课程数量 | |||||
* @param subjectId Int 项目 | |||||
* @return Int 课程数量 | |||||
*/ | |||||
private fun getSubjectForCourseSize(subjectId : Int) : Int { | |||||
return subjectWithCoursePackMap[subjectId]?.let { | |||||
var count = 0 | |||||
it.forEach { coursePack -> | |||||
count += coursePack.childrenCourses.size ?: 0 | |||||
} | |||||
count | |||||
} ?: 0 | |||||
} | |||||
} | } |
private const val NORMAL = "XKL_COURSE_DATA_KEY" | private const val NORMAL = "XKL_COURSE_DATA_KEY" | ||||
private const val SPOKEN = "XKL_SPOKEN_COURSE_DATA_KEY" | private const val SPOKEN = "XKL_SPOKEN_COURSE_DATA_KEY" | ||||
private const val COMPOSITION = "XKL_LOCAL_COMPOSITION_DATA_KEY" | private const val COMPOSITION = "XKL_LOCAL_COMPOSITION_DATA_KEY" | ||||
private const val LITERACY = "XKL_LOCAL_CHINESE_COURSE_KEY" | |||||
private const val LITERACY_PINYING = "XKL_LOCAL_CHINESE_COURSE_KEY" | |||||
private var mDataBase : SQLiteDatabase? = null | private var mDataBase : SQLiteDatabase? = null | ||||
private fun open(base : DbControlBase) { | private fun open(base : DbControlBase) { | ||||
val p = when (base.courseType) { | val p = when (base.courseType) { | ||||
AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> COMPOSITION | AppConstants.COURSE_TYPE_CHINESE_COMPOSITION -> COMPOSITION | ||||
AppConstants.COURSE_TYPE_ENGLISH_SPOKEN -> SPOKEN | AppConstants.COURSE_TYPE_ENGLISH_SPOKEN -> SPOKEN | ||||
AppConstants.COURSE_TYPE_CHINESE_LITERACY -> LITERACY | |||||
AppConstants.COURSE_TYPE_CHINESE_LITERACY,AppConstants.COURSE_TYPE_CHINESE_PINYIN -> LITERACY_PINYING | |||||
else -> NORMAL | else -> NORMAL | ||||
} | } | ||||
mDataBase = SQLiteDatabase.openDatabase(FilePathManager.getCourseDbPath(currentBase).path, | mDataBase = SQLiteDatabase.openDatabase(FilePathManager.getCourseDbPath(currentBase).path, | ||||
when (dbcb.courseType) { | when (dbcb.courseType) { | ||||
AppConstants.COURSE_TYPE_CHINESE_LITERACY -> { | AppConstants.COURSE_TYPE_CHINESE_LITERACY -> { | ||||
word = getString(getColumnIndex("word1")) | |||||
literacyIspolyphone = getInt(getColumnIndex("polyphone")) > 0 | literacyIspolyphone = getInt(getColumnIndex("polyphone")) > 0 | ||||
phonetic_cn = getString(getColumnIndex("phonetic")) | phonetic_cn = getString(getColumnIndex("phonetic")) | ||||
} | } |
import com.jeremyliao.liveeventbus.LiveEventBus | import com.jeremyliao.liveeventbus.LiveEventBus | ||||
import com.suliang.common.base.activity.BaseActivityVM | import com.suliang.common.base.activity.BaseActivityVM | ||||
import com.suliang.common.extension.click | import com.suliang.common.extension.click | ||||
import com.suliang.common.extension.setHtml | |||||
import com.suliang.common.util.DateUtil | import com.suliang.common.util.DateUtil | ||||
import com.suliang.common.util.DrawableUti | import com.suliang.common.util.DrawableUti | ||||
import com.suliang.common.util.image.ImageLoader | import com.suliang.common.util.image.ImageLoader | ||||
//单词内容 | //单词内容 | ||||
bindingWord.incWord.tvWord.apply { | bindingWord.incWord.tvWord.apply { | ||||
//识字需单独处理 | //识字需单独处理 | ||||
text = if (vm.learnData.lesson.courseType == AppConstants.COURSE_TYPE_CHINESE_LITERACY) ViewUtil.literacyToHtmlWord( | |||||
learnWord.word, learnWord.showColor) else learnWord.word | |||||
if (vm.learnData.lesson.courseType == AppConstants.COURSE_TYPE_CHINESE_LITERACY){ | |||||
setHtml(ViewUtil.literacyToHtmlWord(learnWord.word, learnWord.showColor)) | |||||
} else { | |||||
text = learnWord.word | |||||
} | |||||
setTextColor(ContextCompat.getColor(this@LearnWordActivity, learnWord.showColor)) //单词显示颜色 | setTextColor(ContextCompat.getColor(this@LearnWordActivity, learnWord.showColor)) //单词显示颜色 | ||||
} | } | ||||
//音标 | //音标 | ||||
//单词内容 | //单词内容 | ||||
bindingWord.incWord.tvWord.apply { | bindingWord.incWord.tvWord.apply { | ||||
//识字需单独处理 | //识字需单独处理 | ||||
text = if (vm.learnData.lesson.courseType == AppConstants.COURSE_TYPE_CHINESE_LITERACY) ViewUtil.literacyToHtmlWord( | |||||
learnWord.word, learnWord.showColor) else learnWord.word | |||||
if (vm.learnData.lesson.courseType == AppConstants.COURSE_TYPE_CHINESE_LITERACY) { | |||||
setHtml(ViewUtil.literacyToHtmlWord(learnWord.word, learnWord.showColor)) | |||||
} else { | |||||
text = learnWord.word | |||||
} | |||||
setTextColor(ContextCompat.getColor(this@LearnWordActivity, learnWord.showColor)) //单词显示颜色 | setTextColor(ContextCompat.getColor(this@LearnWordActivity, learnWord.showColor)) //单词显示颜色 | ||||
} | } | ||||
//音标 | //音标 | ||||
binding.incControlButton.tvCenter.visibility = View.VISIBLE | binding.incControlButton.tvCenter.visibility = View.VISIBLE | ||||
//音标,显示重读 | //音标,显示重读 | ||||
when(vm.learnData.lesson.coursePackType){ | when(vm.learnData.lesson.coursePackType){ | ||||
AppConstants.COURSEPACK_TYPE_ENGLISH_SOUNDMARK -> View.VISIBLE | |||||
AppConstants.COURSEPACK_TYPE_ENGLISH_SOUNDMARK ->binding.incControlButton.tvRight.visibility = View.VISIBLE | |||||
} | } | ||||
} | } |
when { | when { | ||||
//学后总测试完成,默认无选中 | //学后总测试完成,默认无选中 | ||||
courseDetail.st_after != AppConstants.NOT_DOING -> temposition = -1 | courseDetail.st_after != AppConstants.NOT_DOING -> temposition = -1 | ||||
//进度100 | |||||
courseDetail.courseLearnProgress == AppConstants.DOING_OVER -> temposition = -1 | |||||
//有学习点 | //有学习点 | ||||
courseDetail.course_learn_point.isNotEmpty() -> { | courseDetail.course_learn_point.isNotEmpty() -> { | ||||
run m@{ | run m@{ | ||||
allLesson.forEachIndexed { index, lesson -> | allLesson.forEachIndexed { index, lesson -> | ||||
if ("${lesson.chapterId}_${lesson.lessonId}" == courseDetail.course_learn_point) { | |||||
if (courseDetail.course_learn_point.startsWith("${lesson.chapterId}_${lesson.lessonId}_")) { | |||||
temposition = index | temposition = index | ||||
return@m | return@m | ||||
} | } |
} | } | ||||
override fun loadData() { | override fun loadData() { | ||||
when (totalTestType) { | |||||
AppConstants.TEST_TYPE_BEFORE_TOTAL -> vm.loadTest(totalTestType).observe(this) { | |||||
initTotalBeforeView(it) | |||||
vm.loadTest(totalTestType).observe(this) { | |||||
binding.tvCountTip.text = CourseManager.expectedTestTime(vm.course.courseType, totalTestType, it) | |||||
when (totalTestType) { | |||||
AppConstants.TEST_TYPE_BEFORE_TOTAL -> initTotalBeforeView(it) | |||||
AppConstants.TEST_TYPE_AFTER_TOTAL -> initTotalAfterView() | |||||
} | |||||
} | |||||
} | |||||
/** 学前测试初始 */ | |||||
private fun initTotalBeforeView(testData : List<ExamBean>) { | |||||
//学前总测 | |||||
binding.run { | |||||
tvTitle.setText(R.string.test_total_before_title) | |||||
// button1.run { | |||||
// setText(R.string.start_learn) | |||||
// visibility = View.VISIBLE | |||||
// click { | |||||
// continueLearn(it) | |||||
// } | |||||
// } | |||||
//按钮初始 | |||||
button2.run { | |||||
setText(R.string.start_test) | |||||
click { view -> | |||||
startTest(view) | |||||
} | |||||
} | } | ||||
AppConstants.TEST_TYPE_AFTER_TOTAL -> initTotalAfterView() | |||||
} | } | ||||
} | } | ||||
tvTitle.setText(R.string.tips_current_course_learn_over) | tvTitle.setText(R.string.tips_current_course_learn_over) | ||||
tvMainTip.visibility = View.VISIBLE | tvMainTip.visibility = View.VISIBLE | ||||
//根据测试成绩处理 | //根据测试成绩处理 | ||||
vm.courseDetail.st_before.let { | |||||
vm.courseDetail.st_after.let { | |||||
when (it) { | when (it) { | ||||
AppConstants.NOT_DOING -> { //未测 | AppConstants.NOT_DOING -> { //未测 | ||||
tvMainTip.setText(R.string.test_total_after_tip_1) | tvMainTip.setText(R.string.test_total_after_tip_1) | ||||
button1.run { | |||||
visibility = View.VISIBLE | |||||
setText(R.string.start_learn) | |||||
click { | |||||
continueLearn(it) | |||||
} | |||||
} | |||||
button2.run { | button2.run { | ||||
setText(R.string.test_type_after_total) | setText(R.string.test_type_after_total) | ||||
click { view -> | click { view -> | ||||
} | } | ||||
} | } | ||||
/** 学前测试初始 */ | |||||
private fun initTotalBeforeView(testData : List<ExamBean>) { | |||||
// TODO: 2022/4/21 需要把开始学习给取消了 | |||||
binding.tvCountTip.text = CourseManager.expectedTestTime(vm.course.courseType, totalTestType, testData) | |||||
binding.button1.visibility = View.VISIBLE | |||||
//学前总测 | |||||
binding.run { | |||||
tvTitle.setText(R.string.test_total_before_title) | |||||
button1.run { | |||||
setText(R.string.start_learn) | |||||
click { | |||||
continueLearn(it) | |||||
} | |||||
} | |||||
//按钮初始 | |||||
button2.run { | |||||
setText(R.string.start_test) | |||||
click { view -> | |||||
startTest(view) | |||||
} | |||||
} | |||||
} | |||||
} | |||||
/**继续学习*/ | /**继续学习*/ | ||||
private fun continueLearn(view : View) { | private fun continueLearn(view : View) { |
AppExecutors.io.execute { | AppExecutors.io.execute { | ||||
//读取课程数据 | //读取课程数据 | ||||
// TODO: 2022/5/16 读取课程的sort信息进行保存,针对作文课程,同时需要设置其课程包的进度 | |||||
// TODO: 2022/3/22 读取当前app绑定的课程数据, | // TODO: 2022/3/22 读取当前app绑定的课程数据, | ||||
DbCoursePackManager().queryBindingCoursePack("262,261,264,136,547,615,516,411") | DbCoursePackManager().queryBindingCoursePack("262,261,264,136,547,615,516,411") | ||||
//复制课程的数据库到对应位置 | //复制课程的数据库到对应位置 |
import android.text.Spanned | import android.text.Spanned | ||||
import android.widget.TextView | import android.widget.TextView | ||||
import androidx.annotation.ColorInt | import androidx.annotation.ColorInt | ||||
import androidx.annotation.ColorRes | |||||
import androidx.core.content.ContextCompat | |||||
import com.suliang.common.util.AppGlobals | |||||
import com.suliang.common.util.ColorUtil | import com.suliang.common.util.ColorUtil | ||||
import com.suliang.common.util.os.ScreenUtil | import com.suliang.common.util.os.ScreenUtil | ||||
import java.util.regex.Pattern | import java.util.regex.Pattern | ||||
* @param colorId 处理的颜色id color.xml | * @param colorId 处理的颜色id color.xml | ||||
* @return Spanned 你好 你为大写 | * @return Spanned 你好 你为大写 | ||||
*/ | */ | ||||
fun literacyToHtmlWord(word : String, @ColorInt colorId : Int) : Spanned { | |||||
fun literacyToHtmlWord(word : String, @ColorRes colorId : Int) : String { | |||||
val m = Pattern.compile("\\([\u4e00-\u9fa5]\\)").matcher(word) | val m = Pattern.compile("\\([\u4e00-\u9fa5]\\)").matcher(word) | ||||
val builder = StringBuffer() | val builder = StringBuffer() | ||||
val color : String = ColorUtil.getHexWebString(colorId) | |||||
val color : String = ColorUtil.getHexWebString(ContextCompat.getColor(AppGlobals.application,colorId)) | |||||
var isFind = false | var isFind = false | ||||
var previousEndPosition = 0 //下次循环开始的位置 | var previousEndPosition = 0 //下次循环开始的位置 | ||||
while (m.find()) { | while (m.find()) { | ||||
} else { | } else { | ||||
builder.append("<font color=\"").append(color).append("\">").append(word).append("</font>") | builder.append("<font color=\"").append(color).append("\">").append(word).append("</font>") | ||||
} | } | ||||
println(builder.toString()) | |||||
return Html.fromHtml(builder.toString()) | |||||
return builder.toString() | |||||
} | } | ||||
/** | /** |
app:layout_constraintTop_toTopOf="@+id/button_2" | app:layout_constraintTop_toTopOf="@+id/button_2" | ||||
app:strokeColor="@color/theme_color" | app:strokeColor="@color/theme_color" | ||||
app:strokeWidth="@dimen/line_height" | app:strokeWidth="@dimen/line_height" | ||||
tools:text="@string/start_learn" | |||||
android:visibility="gone" | |||||
/> | /> | ||||
<Button | <Button |
package com.suliang.common.util | package com.suliang.common.util | ||||
import androidx.annotation.ColorInt | |||||
/** | /** | ||||
* author suliang | * author suliang | ||||
* create 2022/4/25 16:29 | * create 2022/4/25 16:29 | ||||
companion object{ | companion object{ | ||||
/** | /** | ||||
* 把一个int颜色值转换成String | * 把一个int颜色值转换成String | ||||
* @param color | |||||
* @param color 非直接资源id,而是转换好的资源,getColor or Color.parse | |||||
* @return | * @return | ||||
*/ | */ | ||||
fun getHexWebString(color : Int) : String { | |||||
fun getHexWebString(@ColorInt color : Int) : String { | |||||
var s = "#" | var s = "#" | ||||
val colorStr = color and -0x1000000 or (color and 0x00ff0000) or (color and 0x0000ff00) or (color and 0x000000ff) | |||||
val colorStr = (color and 0xff000000.toInt()) or (color and 0x00ff0000) or (color and 0x0000ff00) or (color and 0x000000ff) | |||||
var s1 = Integer.toHexString(colorStr) | var s1 = Integer.toHexString(colorStr) | ||||
s1 = s1.substring(2, s1.length) | s1 = s1.substring(2, s1.length) | ||||
s = s + s1 | s = s + s1 |