From 655e9cd56e69d944d22494e02c137eb2913e3f3a Mon Sep 17 00:00:00 2001 From: lvmeng <848755140@qq.com> Date: Tue, 10 Feb 2026 19:02:21 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../activity/FoodCollectionActivity.kt | 11 ++- .../sw/inbound/activity/GoodsListActivity.kt | 92 +++++++++++++++---- .../com/sw/inbound/dialog/AddGoodsDialog.kt | 71 +++++++++++++- .../java/com/sw/inbound/dialog/BaseDialog.kt | 3 +- .../network/interceptor/RequestInterceptor.kt | 4 +- .../java/com/sw/inbound/objbox/FoodModule.kt | 4 +- .../java/com/sw/inbound/objbox/ObjectBox.kt | 9 +- .../java/com/sw/inbound/utils/ImageUtil.kt | 10 ++ .../java/com/sw/inbound/utils/ext/Common.kt | 29 +++++- app/src/main/res/layout/dialog_add_goods.xml | 52 ++++++++--- .../java/com/sw/inbound/ExampleUnitTest.kt | 29 +++++- .../sw/inbound/VectorSimilarityCalculator.kt | 65 +++++++++++++ 12 files changed, 333 insertions(+), 46 deletions(-) create mode 100644 app/src/test/java/com/sw/inbound/VectorSimilarityCalculator.kt diff --git a/app/src/main/java/com/sw/inbound/activity/FoodCollectionActivity.kt b/app/src/main/java/com/sw/inbound/activity/FoodCollectionActivity.kt index 0ed2705..00fa49d 100644 --- a/app/src/main/java/com/sw/inbound/activity/FoodCollectionActivity.kt +++ b/app/src/main/java/com/sw/inbound/activity/FoodCollectionActivity.kt @@ -45,6 +45,7 @@ import com.sw.inbound.utils.ext.gone import com.sw.inbound.utils.ext.hideKeyboard import com.sw.inbound.utils.ext.invisible import com.sw.inbound.utils.ext.startActivity +import com.sw.inbound.utils.ext.toJsonString import com.sw.inbound.utils.ext.toObject import com.sw.inbound.utils.ext.toast import com.sw.inbound.utils.ext.visible @@ -86,6 +87,13 @@ class FoodCollectionActivity : ComponentActivity() { } private val collectionAdapter: FoodCollectionAdapter by lazy { FoodCollectionAdapter(collectList).apply { + setOnItemClickListener { adapter, view, position -> + val file = collectList[position].imageFile ?: return@setOnItemClickListener + ImageUtil.decodeFromFile(file)?.let { bitmap -> + val imageVector = FoodModule.bitmap2FloatArray(bitmap, false) + Timber.tag(TAG).d("向量:${imageVector.toJsonString()}") + } + } addOnItemChildClickListener(R.id.ivDelete) { _, _, position -> collectList[position].let { it.imageFile = null @@ -177,7 +185,7 @@ class FoodCollectionActivity : ComponentActivity() { upload() } - binding.btnTakePhoto.clickWithDebounce { + binding.btnTakePhoto.clickWithDebounce(800) { takePhoto() } binding.btnCollectedGoods.setOnClickListener { @@ -319,6 +327,7 @@ class FoodCollectionActivity : ComponentActivity() { toast("操作失败") return@let } + Timber.tag(TAG).d("向量:${imageVector.toJsonString()}") val foodList = try { FoodModule.queryFoodNameScore(imageVector) } catch (e: DbException) { diff --git a/app/src/main/java/com/sw/inbound/activity/GoodsListActivity.kt b/app/src/main/java/com/sw/inbound/activity/GoodsListActivity.kt index e3c31bc..499a2a4 100644 --- a/app/src/main/java/com/sw/inbound/activity/GoodsListActivity.kt +++ b/app/src/main/java/com/sw/inbound/activity/GoodsListActivity.kt @@ -37,7 +37,11 @@ import com.sw.inbound.model.request.UploadInfo import com.sw.inbound.model.response.DictType import com.sw.inbound.model.response.GoodsInfo import com.sw.inbound.model.response.SearchGoodsInfo +import com.sw.inbound.objbox.Food import com.sw.inbound.objbox.FoodModule +import com.sw.inbound.objbox.FoodModule.IdNameScore +import com.sw.inbound.objbox.Food_ +import com.sw.inbound.objbox.ObjectBox import com.sw.inbound.sdk.SensorScaleUtils import com.sw.inbound.utils.BitmapCropper import com.sw.inbound.utils.CameraUtils @@ -53,6 +57,7 @@ import com.sw.inbound.utils.ext.toast import com.sw.inbound.viewmodel.ReceiptViewModel import com.sw.inbound.viewmodel.UserViewModel import dagger.hilt.android.AndroidEntryPoint +import io.objectbox.query.Query import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import okhttp3.RequestBody @@ -179,6 +184,42 @@ abstract class GoodsListActivity : ComponentActivity() { //Timber.tag(TAG).d("测试:${array[2].toInt()}") userViewModel.getInitInfo() + +// lifecycleScope.launch { +// ObjectBox.put( +// Food( +// name = "测试", +// foodIdx = -100, +// foodVector = floatArrayOf( +// 0.015068196f,0.0f,0.0f,0.0f,0.0037743463f,0.0f,0.0f,0.07893528f,0.0f,0.0f,0.0f,0.0f,0.052832354f,0.0f,0.045785826f,0.0f,6.156802E-4f,0.04242764f,0.0f,0.0f,0.0f,0.0f,0.11469748f,0.13930011f,0.005731758f,0.03159248f,0.018799406f,0.028927676f,0.03472497f,0.01896616f,0.078822434f,0.0f,0.015187703f,0.0f,0.033177234f,0.07078301f,0.0f,0.0f,0.012238876f,0.0f,0.0f,0.0f,0.0f,0.0f,0.10691055f,0.008628067f,0.0f,0.0f,0.0f,0.0f,0.0f,0.06886323f,0.0f,0.0f,0.10460233f,0.0f,0.0f,0.0f,0.0f,0.0f,0.012850592f,0.0f,0.0f,0.103946045f,0.0f,0.018065454f,0.046292588f,0.063853905f,0.0f,0.10074362f,0.110680245f,0.10660499f,0.0f,0.06775707f,0.0f,0.0f,0.0f,0.0f,0.01639176f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.024850294f,0.0f,0.05308442f,0.0f,0.0f,0.0f,0.028708044f,0.02787582f,0.0f,0.0f,0.0f,0.0f,0.0f,0.027483912f,0.11719905f,0.04781422f,0.09033941f,0.09655397f,0.0032244714f,0.0f,0.0f,0.09580024f,0.07075415f,0.0876085f,0.0f,0.08756652f,2.2919098E-4f,0.019845076f,0.0f,0.0f,0.0f,0.04727701f,0.007276267f,0.0f,0.12660357f,0.03222255f,0.00182945f,0.0f,0.0f,0.0f,0.0f,0.0f,0.09080463f,0.0043369643f,0.0f,0.0f,0.0f,0.0f,0.0f,0.073994264f,0.0f,0.030294247f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.04890032f,0.0f,0.05318369f,0.0f,0.0f,0.0510094f,0.0f,0.0f,0.0f,0.12696978f,0.0f,0.21870367f,0.0f,0.0f,0.0f,0.0f,0.022256335f,0.13343737f,0.0f,0.0f,0.0f,0.0f,0.025192281f,0.1621841f,0.031685397f,0.0f,0.0f,0.03057069f,0.011333849f,0.0f,0.0f,0.11482361f,0.10645431f,0.0f,0.0f,0.0f,0.039949007f,0.0f,0.018850718f,0.0f,0.0f,0.0f,0.026081126f,0.0f,0.07934742f,0.0f,0.0f,0.0f,0.0f,0.0f,0.007998445f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.098366655f,0.0f,0.01606297f,0.16557153f,0.0f,0.0f,0.0f,0.0f,0.042638786f,0.024310581f,0.0f,0.027677892f,5.940642E-4f,0.0f,0.0f,0.0f,0.0f,0.05605889f,0.0f,0.0f,0.05216231f,0.080610394f,0.0f,0.0f,0.0f,0.0f,0.0f,0.07294793f,0.0f,0.02029506f,0.0f,0.0f,0.0f,0.12797904f,0.16668096f,0.083295606f,0.07768397f,0.07725612f,0.0f,0.0f,0.07259326f,0.110221304f,0.0f,0.0f,0.0f,0.0f,0.0f,0.027140126f,0.0f,0.053474665f,0.0f,0.018286237f,0.0f,0.0f,0.12152021f,0.0f,0.0f,0.0822232f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.04146023f,0.0f,0.034810524f,0.0f,0.00393797f,0.0f,0.032150663f,0.0f,0.0f,0.0f,0.0f,0.097777024f,0.0f,0.0f,0.0f,0.078797914f,0.0f,0.1292709f,0.0f,0.010623558f,0.0f,0.08360209f,0.0f,0.0f,0.122683614f,0.0f,0.0f,0.0f,0.0f,0.10111214f,0.10537941f,0.0f,0.0f,0.0f,0.0f,0.06272928f,0.0f,0.029668529f,0.049171254f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.032665383f,0.0f,0.0f,0.044802308f,0.0f,0.0f,0.05388319f,0.0f,0.0f,0.079517856f,0.012373011f,0.0f,0.01629987f,0.014890053f,0.0f,0.027798127f,0.0f,0.051028676f,0.15331483f,0.024111472f,0.0f,0.0f,0.0f,0.0f,0.0f,0.013699274f,0.0f,0.0f,0.07011116f,0.03022409f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.10939847f,0.0f,0.0f,0.0f,0.030306451f,0.0f,0.0f,0.12335773f,0.0f,0.0f,0.09099765f,0.0f,0.0f,0.0073862355f,0.0f,0.027847463f,0.0840776f,0.04207977f,0.046206567f,0.06679146f,0.0f,0.0f,0.01625976f,0.022998374f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.059722353f,0.0f,0.012246756f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.04984296f,0.0f,0.1435546f,0.0f,0.14667304f,0.079418436f,0.1305641f,0.014777453f,0.0f,0.020115053f,0.05619832f,0.011520876f,0.0f,0.11993748f,0.009492612f,0.019984039f,0.0f,0.0f,0.0f,0.0f,0.043548502f,0.0f,0.0f,0.0f,0.0f,0.15310751f,0.0f,0.0f,0.0f,0.0f,0.0f,0.018038996f,0.0021733972f,0.0f,0.0f,0.0f,0.0f,0.060995787f,0.06326715f,0.0f,0.06896745f,0.013745607f,5.018817E-4f,0.0f,0.0f,0.14184067f,0.019447664f,0.047488734f,0.13301876f,0.0f,0.0f,0.06715185f,0.0f,0.0f,0.0025059544f,0.0013816518f,0.0f,0.00415278f,0.17231767f,0.0073697185f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0017814273f,0.040113796f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.016738398f,0.0f,0.10465313f,0.0f,0.057283692f,0.0f,0.05406501f,0.0f,0.012632326f,0.0f,0.0f,0.0f,0.10440692f,0.0f,0.0047152108f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.11544036f +// ) +// ) +// ) +// ObjectBox.remove("测试") +// ObjectBox.safeDbOp { +// val vector2 = floatArrayOf( +// 0.029274145f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.04849013f,0.0f,0.0f,0.0030461443f,0.0f,0.04333778f,0.0f,0.036458552f,0.0f,0.0f,0.032146808f,0.0f,0.0f,0.0f,0.0f,0.12563168f,0.16337962f,0.0086008925f,0.028651662f,0.05676712f,0.038951095f,0.035215054f,0.023515426f,0.09426005f,0.0f,0.0f,0.0f,0.019520408f,0.09774056f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.12273409f,0.03317896f,0.0f,0.0f,0.0f,0.0f,0.0f,0.056036845f,0.0f,0.005601604f,0.09232295f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.10639726f,0.017117623f,0.0f,0.04106111f,0.06582154f,0.0f,0.10570599f,0.10395363f,0.11154216f,0.0f,0.09019618f,0.0f,0.0f,0.0f,0.0f,0.008780864f,0.0f,0.0f,0.01997713f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.016066022f,0.020096382f,0.0f,0.05578338f,0.0f,0.0f,0.0f,0.048834037f,0.031760734f,0.0f,0.0f,0.0f,0.0f,0.0f,0.02459963f,0.11993096f,0.047805987f,0.070974134f,0.10536186f,0.0f,0.0f,0.0f,0.111894555f,0.08973926f,0.071053386f,0.0f,0.071883f,0.005135076f,0.0f,0.0f,0.0f,0.0f,0.023139987f,0.027882056f,0.0f,0.12620124f,0.05076331f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.06944067f,0.0146693f,0.0f,0.0f,0.0f,0.0f,0.00978479f,0.04965295f,0.0f,0.03953311f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.05496083f,0.0f,0.05957852f,0.0f,0.0f,0.05285405f,0.0f,0.0f,0.0f,0.10977843f,0.0f,0.21329264f,0.0f,0.0f,0.0f,0.0f,0.022029493f,0.12511873f,0.0f,0.0f,0.0f,0.0f,0.015391711f,0.1697028f,0.035269253f,0.0f,0.0f,0.0070471396f,0.0f,0.0f,0.0f,0.123943165f,0.10272677f,0.0f,0.0f,0.0f,0.06351426f,0.0f,0.009808158f,0.0f,0.0f,0.0f,0.02582221f,0.0f,0.0745801f,0.0f,0.0f,0.023285847f,0.0f,0.0f,0.017162288f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.09181752f,0.0f,0.007880242f,0.15574618f,0.0f,0.0f,0.0f,0.0f,0.02478441f,0.039601766f,0.0f,0.049401764f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0793202f,0.0f,0.0f,0.071133174f,0.09675928f,0.0f,0.015621623f,0.0f,0.0f,0.0f,0.08347399f,0.009147923f,0.0f,0.0f,0.0f,0.0f,0.14187747f,0.15219086f,0.12055488f,0.07175866f,0.07192898f,0.0f,0.0f,0.04634941f,0.12534219f,0.0f,0.0f,0.0f,0.008665879f,0.0f,0.040081337f,0.0f,0.06729515f,0.0f,0.058273762f,0.0020215393f,0.0f,0.10878004f,0.0f,0.0f,0.09762441f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.03849448f,0.0f,0.03300536f,0.0f,0.0f,0.013231625f,0.018584426f,0.0f,0.0f,0.0f,0.0f,0.08124468f,0.0f,0.0f,0.0f,0.060708806f,0.0f,0.11115098f,0.0f,0.0f,0.0f,0.0803424f,0.0f,0.0f,0.115781434f,0.0f,0.00764197f,0.0f,0.0f,0.121340856f,0.0869794f,0.0f,0.0f,0.0f,0.0f,0.045324527f,0.0f,0.015057986f,0.048937548f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.030864827f,0.0f,0.0029875587f,0.03196471f,0.0f,0.0f,0.054534424f,0.0f,0.0f,0.07863297f,0.019617077f,0.0f,0.026181744f,0.0f,0.0f,0.021914937f,0.0f,0.063720085f,0.16607703f,0.006567324f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0017898319f,0.0f,0.0f,0.04841979f,0.0044351136f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.15329078f,0.0f,0.0f,0.0f,0.030429695f,0.0f,0.0f,0.11840538f,0.0f,0.0f,0.107368395f,0.014730752f,0.0f,0.0f,0.0f,0.030180579f,0.039591953f,0.03209204f,0.048180148f,0.0676186f,0.0f,0.0f,0.03614289f,0.030257396f,1.5626202E-4f,0.018185573f,0.0f,0.0f,0.0f,0.0f,0.055325508f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.051894154f,0.0f,0.12869093f,0.0f,0.122797504f,0.083724305f,0.12840301f,0.0f,0.0f,0.0f,0.05686797f,0.0f,0.0f,0.11015593f,0.018203156f,0.020094728f,0.0f,0.0f,0.0f,0.0f,0.058597155f,0.0f,0.0f,0.0f,0.0f,0.12797132f,0.0f,0.006606713f,0.0f,0.0f,0.0f,0.028628595f,0.0f,0.0f,0.0f,0.0f,0.0f,0.050383586f,0.07132696f,0.0f,0.092209496f,0.0f,0.0f,0.0f,0.0f,0.14604862f,0.01660271f,0.057229653f,0.13104743f,0.0f,0.0f,0.06136706f,0.0f,0.0f,0.0f,0.0011910667f,0.0f,0.0f,0.15921566f,0.0f,0.0f,0.0f,0.0f,0.007558685f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.007532647f,0.05110198f,0.00667856f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0016389234f,0.0f,0.0f,0.0f,0.0f,0.018518167f,0.0f,0.08580791f,0.0f,0.06099585f,0.0f,0.0366169f,0.0f,0.0f,0.0f,0.0f,0.0f,0.073218584f,0.0f,0.0f,0.0f,0.008933658f,0.0f,0.0f,0.0f,0.0f,0.0f,0.116691895f +// ) +// ObjectBox.getBox()?.let { +// val query: Query? = it.query( +// Food_.foodVector +// .nearestNeighbors(vector2, 5) +// )?.build() +// try { +// val list = query?.findIdsWithScores() +// val resultList = mutableListOf() +// list?.forEach { idWithScore -> +// val food = it.get(idWithScore.id) +// resultList.add("${food.name}|${food.id}|${idWithScore.score}") +// } +// Timber.tag(TAG).d("比较结果:${resultList.joinToString(separator = ",")}") +// } finally { +// // 先关闭Query,释放Cursor +// query?.close() +// } +// } +// } +// } } private var weightCallback: ((weight: Int) -> Unit)? = null @@ -336,10 +377,23 @@ abstract class GoodsListActivity : ComponentActivity() { if (newBmp.isRecycled.not()) { newBmp.recycle() } - if (foodList.isEmpty()) { - recognizeFoodError() + val count = foodList.count { it.score < 0.15 } + if (count == 0) { + //未识别到满足相似度>=0.85的,显示识别率最高的 + var tempList = foodList.filter { it.name.contains("黑袋子").not() } + if (tempList.isEmpty()) { + recognizeFoodError() + return@let + } + tempList = tempList.subList(0, 1) + tempList.forEach { it.name = it.name.split("WP")[0] } + recognizeGoodsList(tempList) return@let } + //if (foodList.isEmpty()) { + // recognizeFoodError() + // return@let + //} foodList.forEach { it.name = it.name.split("WP")[0] } @@ -358,23 +412,27 @@ abstract class GoodsListActivity : ComponentActivity() { } return@let } - receiptViewModel.recognizeGoodsList( - //nameList = foodList, - scoreList = foodList, - ) { goodsList -> - runOnUiThread { - if (isAgainRecognize) { - Loading.dismiss() - recognizeCallback?.invoke(goodsList) - isAgainRecognize = false - return@runOnUiThread - } - handleGoodsResult( - goodsList = if (goodsList.size == foodList.size) goodsList else mutableListOf(), + recognizeGoodsList(foodList) + } + } + + private fun recognizeGoodsList(foodList: List) { + receiptViewModel.recognizeGoodsList( + //nameList = foodList, + scoreList = foodList, + ) { goodsList -> + runOnUiThread { + if (isAgainRecognize) { + Loading.dismiss() + recognizeCallback?.invoke(goodsList) + isAgainRecognize = false + return@runOnUiThread + } + handleGoodsResult( + goodsList = if (goodsList.size == foodList.size) goodsList else mutableListOf(), // file = null, // name = foodList.joinToString(",") - ) - } + ) } } } diff --git a/app/src/main/java/com/sw/inbound/dialog/AddGoodsDialog.kt b/app/src/main/java/com/sw/inbound/dialog/AddGoodsDialog.kt index 674598b..ca5da60 100644 --- a/app/src/main/java/com/sw/inbound/dialog/AddGoodsDialog.kt +++ b/app/src/main/java/com/sw/inbound/dialog/AddGoodsDialog.kt @@ -4,6 +4,7 @@ import android.content.Context import android.net.Uri import android.view.LayoutInflater import android.view.View +import android.widget.EditText import android.widget.FrameLayout import android.widget.ImageView import android.widget.TextView @@ -120,7 +121,28 @@ class AddGoodsDialog( arrowImage = binding.ivProcurementArrow, list = GlobalData.unitTypeList, height = 2 * 71.dp - ) + ) { + val warehouseUnit = binding.tvWarehouseUnit.text.toString().trim() + if (warehouseUnit.isBlank()) return@showDropDownList + when (it.value) { + "千克", "公斤" -> { + setGoodsCount(warehouseUnit, "1", "2", "1000") + } + "斤" -> { + setGoodsCount(warehouseUnit, "0.5", "1", "500") + } + "克" -> { + setGoodsCount(warehouseUnit, "0.001", "0.002", "1") + } + else -> { + val procurementUnit = binding.tvProcurementUnit.text.toString().trim() + val warehouseUnit = binding.tvWarehouseUnit.text.toString().trim() + binding.etGoodsCount.setText( + if (procurementUnit == warehouseUnit) "1" else "" + ) + } + } + } // showDropDownList( // binding.flGoodsType, // textView = binding.tvGoodsType, @@ -141,6 +163,51 @@ class AddGoodsDialog( ) { binding.tvSelectUseUnit.text = it.value binding.tvSelectProcurementUnit.text = it.value + val procurementUnit = binding.tvProcurementUnit.text.toString().trim() + when (it.value) { + "千克", "公斤" -> { + binding.etUseUnit.setText("1000") + setGoodsCount(procurementUnit, "1", "0.5", "0.001") + } + "斤" -> { + binding.etUseUnit.setText("500") + setGoodsCount(procurementUnit, "2", "1", "0.002") + } + "克" -> { + binding.etUseUnit.setText("1") + setGoodsCount(procurementUnit, "1000", "500", "1") + } + else -> { + binding.etUseUnit.setText("") + + val procurementUnit = binding.tvProcurementUnit.text.toString().trim() + val warehouseUnit = binding.tvWarehouseUnit.text.toString().trim() + binding.etGoodsCount.setText( + if (procurementUnit == warehouseUnit) "1" else "" + ) + } + } + } + } + + private fun setGoodsCount(unit:String, kgCount:String, jinCount:String, gCount:String) { + when (unit) { + "千克", "公斤" -> { + binding.etGoodsCount.setText(kgCount) + } + "斤" -> { + binding.etGoodsCount.setText(jinCount) + } + "克" -> { + binding.etGoodsCount.setText(gCount) + } + else -> { + val procurementUnit = binding.tvProcurementUnit.text.toString().trim() + val warehouseUnit = binding.tvWarehouseUnit.text.toString().trim() + binding.etGoodsCount.setText( + if (procurementUnit == warehouseUnit) "1" else "" + ) + } } } @@ -227,7 +294,7 @@ class AddGoodsDialog( return } val goodsCount = binding.etGoodsCount.text.trim().toString() - if (costValue.isBlank()) { + if (goodsCount.isBlank()) { context.toast("请输入采购数量") return } diff --git a/app/src/main/java/com/sw/inbound/dialog/BaseDialog.kt b/app/src/main/java/com/sw/inbound/dialog/BaseDialog.kt index 3f3301e..69a3eca 100644 --- a/app/src/main/java/com/sw/inbound/dialog/BaseDialog.kt +++ b/app/src/main/java/com/sw/inbound/dialog/BaseDialog.kt @@ -7,6 +7,7 @@ import android.graphics.drawable.ColorDrawable import android.os.Bundle import android.view.Gravity import android.view.View +import com.sw.inbound.GlobalData import com.sw.inbound.R import com.sw.inbound.activity.FoodCollectionActivity import com.sw.inbound.activity.GoodsListActivity @@ -17,7 +18,7 @@ abstract class BaseDialog( context: Context, var defWidth: Int = 1500.dp, // var defHeight: Int = 900.dp - var defHeight: Int = 750.dp + var defHeight: Int = if ("f0bcabbb-0d58-3b14-8bed-9863b7ec61ef" == GlobalData.deviceId) 750.dp else 900.dp ) : Dialog(context, R.style.DialogTheme) { override fun onCreate(savedInstanceState: Bundle?) { diff --git a/app/src/main/java/com/sw/inbound/network/interceptor/RequestInterceptor.kt b/app/src/main/java/com/sw/inbound/network/interceptor/RequestInterceptor.kt index 1f4ac76..cc9a389 100644 --- a/app/src/main/java/com/sw/inbound/network/interceptor/RequestInterceptor.kt +++ b/app/src/main/java/com/sw/inbound/network/interceptor/RequestInterceptor.kt @@ -17,8 +17,8 @@ class RequestInterceptor : Interceptor { .header("Content-Type", "application/json") .header("Accept", "application/json") .header("deviceId", GlobalData.deviceId) -// .header("X-DEVICE-CODE", GlobalData.deviceId) - .header("X-DEVICE-CODE", "bcf396ed-78f6-3864-9837-7c37c5b2ec41") + .header("X-DEVICE-CODE", GlobalData.deviceId) +// .header("X-DEVICE-CODE", "bcf396ed-78f6-3864-9837-7c37c5b2ec41") .header("x-access-token", GlobalData.appToken) .header("authorization", "57ee87183f2a4fa59683ec9ef41c8f5d") // .header("Authorization", "Bearer ${getToken()}") diff --git a/app/src/main/java/com/sw/inbound/objbox/FoodModule.kt b/app/src/main/java/com/sw/inbound/objbox/FoodModule.kt index 6f2c71c..e6e7392 100644 --- a/app/src/main/java/com/sw/inbound/objbox/FoodModule.kt +++ b/app/src/main/java/com/sw/inbound/objbox/FoodModule.kt @@ -137,12 +137,14 @@ object FoodModule { } suspend fun getFoodScoreList(bitmap: Bitmap, queryCount: Int = 15): List { val floatArray = bitmap2FloatArray(bitmap, false) ?: return emptyList() + Timber.tag("FoodModule").d("向量:${floatArray.toJsonString()}") val nameScoreList = queryFoodNameScore(floatArray, queryCount) if (nameScoreList.isEmpty()) { return emptyList() } + //暂时不过滤 val maxScoreList = nameScoreList - .filter { it.score < 0.15 } + //.filter { it.score < 0.15 } .groupBy { it.name } .map { (_, value) -> value.minByOrNull { it.score }!! } .toMutableList() diff --git a/app/src/main/java/com/sw/inbound/objbox/ObjectBox.kt b/app/src/main/java/com/sw/inbound/objbox/ObjectBox.kt index 0a58e99..013b60e 100644 --- a/app/src/main/java/com/sw/inbound/objbox/ObjectBox.kt +++ b/app/src/main/java/com/sw/inbound/objbox/ObjectBox.kt @@ -177,11 +177,12 @@ object ObjectBox { } suspend fun filter(name:String?) = safeDbOp { - var list = getBox()?.all?.distinctBy { it.name } + val list = getBox()?.all?.distinctBy { it.name } if (name.isNullOrBlank().not()) { - list?.filter { it.name?.contains(name!!) == true } - } - list?:emptyList() + list?.filter { it.name?.contains(name) == true } + } else { + list + }?:emptyList() } suspend fun remove(name:String) = safeDbOp { diff --git a/app/src/main/java/com/sw/inbound/utils/ImageUtil.kt b/app/src/main/java/com/sw/inbound/utils/ImageUtil.kt index 5f1369f..3a3d097 100644 --- a/app/src/main/java/com/sw/inbound/utils/ImageUtil.kt +++ b/app/src/main/java/com/sw/inbound/utils/ImageUtil.kt @@ -4,6 +4,7 @@ import android.content.Context import android.graphics.Bitmap import android.graphics.BitmapFactory import android.net.Uri +import java.io.File object ImageUtil { fun uriToBitmap(context: Context, uri: Uri): Bitmap? { @@ -23,4 +24,13 @@ object ImageUtil { } } + // 直接解码文件路径 + fun decodeFromFile(file: File): Bitmap? { + return if (file.exists()) { + BitmapFactory.decodeFile(file.absolutePath) + } else { + null + } + } + } \ No newline at end of file diff --git a/app/src/main/java/com/sw/inbound/utils/ext/Common.kt b/app/src/main/java/com/sw/inbound/utils/ext/Common.kt index 639716c..9272509 100644 --- a/app/src/main/java/com/sw/inbound/utils/ext/Common.kt +++ b/app/src/main/java/com/sw/inbound/utils/ext/Common.kt @@ -154,13 +154,36 @@ fun EditText.addOnActionSearchListener(searchCallback: () -> Unit) { } +//fun View.clickWithDebounce(delay: Long = 300, action: () -> Unit) { +// var job: Job? = null +// setOnClickListener { +// job?.cancel() +// job = CoroutineScope(Dispatchers.Main).launch { +// delay(delay) +// action() +// } +// } +//} + +/** + * 极简版防重复点击扩展函数 + * @param delay 防抖时间(默认300ms) + * @param action 点击执行逻辑 + */ fun View.clickWithDebounce(delay: Long = 300, action: () -> Unit) { var job: Job? = null setOnClickListener { job?.cancel() - job = CoroutineScope(Dispatchers.Main).launch { - delay(delay) - action() + // 用View的tag存储是否可点击的状态(默认可点击) + if (tag as? Boolean ?: true) { + tag = false // 标记为不可点击 + action() // 立即执行点击逻辑 + + // 启动协程,延迟后恢复可点击状态 + CoroutineScope(Dispatchers.Main).launch { + delay(delay) + tag = true // 恢复可点击 + } } } } diff --git a/app/src/main/res/layout/dialog_add_goods.xml b/app/src/main/res/layout/dialog_add_goods.xml index 134f4ee..a9b1bb0 100644 --- a/app/src/main/res/layout/dialog_add_goods.xml +++ b/app/src/main/res/layout/dialog_add_goods.xml @@ -160,7 +160,10 @@ android:orientation="vertical" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/flImageCollect"> - + @@ -183,10 +186,13 @@ android:textStyle="bold" /> + @@ -239,10 +245,13 @@ + + android:layout_height="wrap_content"> + @@ -333,10 +345,13 @@ + + android:layout_height="wrap_content"> + @@ -448,20 +466,25 @@ tools:text="瓶" /> + - + @@ -521,7 +544,7 @@ android:background="@drawable/bg_white_radius10_stroke2" android:gravity="center" android:hint="请录入" - android:inputType="number" + android:inputType="numberDecimal" android:maxLines="1" android:paddingStart="25dp" android:paddingEnd="25dp" @@ -578,7 +601,10 @@ android:textStyle="bold" android:text="元" /> - + diff --git a/app/src/test/java/com/sw/inbound/ExampleUnitTest.kt b/app/src/test/java/com/sw/inbound/ExampleUnitTest.kt index 235a850..a9f1036 100644 --- a/app/src/test/java/com/sw/inbound/ExampleUnitTest.kt +++ b/app/src/test/java/com/sw/inbound/ExampleUnitTest.kt @@ -9,7 +9,7 @@ import org.junit.Test */ class ExampleUnitTest { - @Test +// @Test fun addition_isCorrect() { // println(4, 2 + 2) val decimalPlaces = 2 @@ -29,7 +29,7 @@ class ExampleUnitTest { println("$tag, result = $msg") } - @Test +// @Test fun testFloat() { log("0.00", "0.00".isValidFloat()) log("0.01", "0.01".isValidFloat()) @@ -67,4 +67,29 @@ class ExampleUnitTest { return matches(decimalRegex) } + + @Test + fun vectorSimilarity() { +// val vector = floatArrayOf( +// 0.044965353f,0.0f,0.0f,0.0f,0.0f,8.377289E-4f,0.0f,0.08697582f,0.0f,0.0f,0.0f,0.0f,0.056673132f,0.0048905406f,0.057954628f,0.0f,0.017238954f,0.03816336f,0.0f,0.0f,4.9872044E-5f,0.0f,0.103112906f,0.12678225f,0.028405422f,0.039923374f,0.0045142793f,0.030780189f,0.0f,0.050326712f,0.03636783f,0.0f,0.020746801f,0.0f,0.02912772f,0.07644723f,0.0f,0.0f,0.012707499f,0.0f,0.0f,0.0f,0.0f,0.0f,0.05465086f,0.019942753f,0.0f,0.0f,0.0f,0.0f,0.0f,0.09032286f,0.0f,0.025173543f,0.09341076f,0.002681128f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.032784935f,0.09999022f,0.0f,0.056982663f,0.036085635f,0.076223254f,0.0f,0.078823626f,0.09971455f,0.101214215f,0.0f,0.062269375f,0.0f,0.0f,0.0f,0.0f,0.043811474f,0.016228097f,0.0f,0.005065734f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.02193476f,0.0f,0.05240194f,0.0f,0.0f,0.0f,0.0f,0.013821804f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.13496852f,0.046263166f,0.084122986f,0.09910474f,0.026525209f,0.0f,0.0f,0.100664f,0.052160427f,0.074085265f,0.0124217225f,0.062484015f,0.0f,0.03609839f,0.0f,0.0f,0.0f,0.043177273f,0.0f,0.0f,0.11422996f,0.033960324f,0.014480866f,0.0f,0.0f,0.0f,0.0f,0.0f,0.09051817f,0.012583549f,0.0f,0.013904583f,0.0f,0.0f,0.0f,0.09033129f,0.0f,0.0f,0.00943393f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.021974336f,0.0f,0.07020068f,0.0f,0.0f,0.028822942f,0.0f,0.0f,0.0f,0.100173116f,0.0f,0.20344076f,0.0f,0.0f,0.0f,0.0f,0.014526786f,0.16405603f,0.0f,0.0f,0.0f,0.0f,0.010118703f,0.20771901f,0.021986803f,0.017206948f,0.0f,0.035743967f,0.0233565f,0.0f,0.0f,0.08678867f,0.1028636f,0.0f,0.0f,0.0f,0.013465163f,0.0f,0.01907301f,0.02529738f,0.0f,0.0f,0.0035515137f,0.0f,0.071397446f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0051259883f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.121495984f,0.0f,0.023764635f,0.16825739f,0.0f,0.0f,0.0f,0.0f,0.046005785f,0.03436156f,0.0f,0.021297242f,0.014054135f,0.0f,0.0f,0.0f,0.0f,0.047426794f,0.0f,0.0f,0.053715404f,0.08112736f,0.0f,0.0f,0.0f,0.0f,0.0f,0.044106703f,0.0f,0.04367752f,0.0f,0.0f,0.0f,0.15173462f,0.16032499f,0.06236599f,0.08927157f,0.054597132f,0.0f,0.0f,0.109912835f,0.11166212f,0.0f,0.0f,0.0f,0.0f,0.0f,0.013451309f,0.0f,0.04017654f,0.0f,0.006972992f,0.011281665f,0.0f,0.1272958f,0.0f,0.0f,0.07654262f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.022481557f,0.0f,0.041888714f,0.0f,0.008270643f,0.0055315774f,0.037642997f,0.0f,0.011266245f,0.0f,0.0f,0.11921886f,0.0f,0.0f,0.0f,0.09897007f,0.0f,0.11849627f,0.0f,0.003410538f,0.0f,0.09413481f,0.0f,0.0f,0.15098546f,0.0f,0.0f,0.0f,0.021952175f,0.11610187f,0.10997474f,0.0f,0.0f,0.0f,0.0f,0.0730338f,0.0f,0.008537221f,0.08227911f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.010958639f,0.0f,0.009177053f,0.03729424f,0.0f,0.0024872338f,0.054441202f,0.0f,0.0f,0.08428903f,0.0f,0.0f,0.022766057f,0.0021686116f,0.0f,0.001098188f,0.014538243f,0.05301009f,0.12891653f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.060878154f,0.018891823f,0.0f,0.10552897f,0.06017957f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.112172805f,0.0f,0.0f,0.0f,0.05110971f,0.0f,0.0f,0.08507675f,0.0f,0.0f,0.06618395f,0.011874482f,0.0f,0.008187234f,0.0f,0.029391974f,0.104699776f,0.041166715f,0.057819895f,0.041235283f,0.0f,0.0f,0.00257591f,7.3478563E-4f,0.0f,0.0f,0.0f,0.0f,0.0f,0.005514997f,0.067062065f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.054157283f,0.0f,0.12115284f,0.0f,0.12101457f,0.075238846f,0.121489145f,0.028768577f,0.0f,0.02615311f,0.019434305f,0.0142671075f,0.0f,0.12127015f,0.0f,0.031494588f,0.0f,0.0f,0.0f,0.0f,0.030308783f,0.0f,0.0f,0.0f,0.0f,0.15617357f,0.0f,0.0f,0.0f,0.0f,0.0f,0.01530996f,0.008721488f,0.0f,0.0f,0.0f,0.0f,0.055147484f,0.043269463f,0.0f,0.07176485f,0.0f,0.0f,0.0f,0.0f,0.14983608f,0.008038647f,0.04870005f,0.1245386f,0.0f,0.0f,0.08583651f,0.0f,0.0f,0.0f,0.016693637f,0.0f,0.0060664704f,0.17301567f,8.5748E-4f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.002572342f,0.023325972f,0.021881843f,0.0f,0.0f,0.0f,0.0f,0.01587723f,0.022998065f,0.0f,0.0f,0.0f,0.0f,0.0f,0.011861979f,0.09544845f,0.0f,0.055203125f,0.0f,0.0629969f,0.0f,0.0035823747f,0.0f,0.0f,0.007002083f,0.10776374f,0.0f,0.017752303f,0.0f,0.0061969324f,0.0f,0.0f,0.009520484f,0.0f,0.0f,0.102450386f +// ) +// val vector2 = floatArrayOf( +// 0.04888371f,0.0f,0.0f,0.0f,0.0029784122f,0.002596595f,0.0f,0.09006795f,0.0f,0.0f,0.0f,0.0f,0.055271827f,0.0f,0.05845978f,0.0f,0.019993817f,0.041442946f,0.0f,0.0f,0.0f,0.0f,0.110088825f,0.12857845f,0.027423449f,0.042506482f,0.0062566767f,0.02848646f,0.0f,0.053226694f,0.0363839f,0.0f,0.024389764f,0.0f,0.024480496f,0.07460136f,0.0f,0.0f,0.0095814075f,0.0f,0.0f,0.0f,0.0f,0.0f,0.054666847f,0.016595673f,0.0f,0.0f,0.0f,0.0f,0.0f,0.090781584f,0.0f,0.029958958f,0.08923955f,0.0035447674f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.030632209f,0.098676704f,0.0f,0.05408989f,0.037333414f,0.07468324f,0.0f,0.077006094f,0.10075786f,0.10385432f,0.0f,0.068913125f,0.0f,0.0f,0.0f,0.0f,0.05182277f,0.015297369f,0.0f,0.0057702474f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.022514984f,0.0f,0.04740151f,0.0f,0.0f,0.0f,0.0f,0.011726161f,0.0f,0.0f,0.0f,0.0f,0.0f,0.001217202f,0.13705015f,0.05138347f,0.0816593f,0.096534394f,0.033242907f,0.0f,0.0f,0.09895034f,0.052346945f,0.07408804f,0.009087045f,0.06717835f,0.0f,0.037536476f,0.0f,0.0f,0.0f,0.045073338f,0.0f,0.0f,0.109948605f,0.033441752f,0.0144465f,0.0f,0.0f,0.0f,0.0f,0.0f,0.09093299f,0.01587698f,0.0f,0.016737117f,0.0f,0.0f,0.0f,0.09095665f,0.0f,0.0f,0.007922342f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.028204395f,0.0f,0.06497759f,0.0f,0.0f,0.03524986f,0.0f,0.0f,0.0f,0.098453656f,0.0f,0.20563814f,0.0f,0.0f,0.0f,0.0f,0.018535f,0.16479786f,0.0f,0.0f,0.0f,0.0f,0.014758027f,0.20929694f,0.017117912f,0.010678992f,0.0f,0.034372084f,0.020094762f,0.0f,0.0f,0.08637927f,0.10176056f,0.0f,0.0f,0.0f,0.011331189f,0.0f,0.018886581f,0.026822357f,0.0f,0.0f,0.0070237503f,0.0f,0.07202005f,0.0f,0.0f,0.0f,0.0f,0.0f,0.013319949f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.11933144f,0.0f,0.021441849f,0.1652874f,0.0f,0.0f,0.0f,0.0f,0.04828791f,0.029381368f,0.0f,0.023457773f,0.015665215f,0.0f,0.0f,0.0f,0.0f,0.041535854f,0.0f,0.0f,0.048669547f,0.08775835f,0.0f,0.0f,0.0f,0.0f,0.0f,0.041737933f,0.0f,0.042860966f,0.0f,0.0f,0.0f,0.15421067f,0.15791793f,0.055794608f,0.09275912f,0.0545075f,0.0f,0.0f,0.10848742f,0.11504846f,0.0f,0.0f,0.0f,0.0f,0.0f,0.011648767f,0.0f,0.036499906f,0.0f,0.0054769856f,0.0141694015f,0.0f,0.1272967f,0.0f,0.0f,0.08008197f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0037580582f,0.0f,0.0f,0.02007829f,0.0f,0.042384353f,0.0f,0.0066040033f,0.0018169946f,0.03661767f,0.0f,0.01246191f,0.0f,0.0f,0.120526984f,0.0f,0.0f,0.0f,0.098151006f,0.0f,0.12102959f,0.0f,0.008543933f,0.0f,0.09429267f,0.0f,0.0f,0.14950682f,0.0f,0.0f,0.0f,0.023073947f,0.11525905f,0.106162556f,0.0f,0.0f,0.0f,0.0f,0.071997344f,0.0f,0.004406387f,0.089178264f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.012335265f,0.0f,0.012351429f,0.03485895f,0.0f,0.0036322998f,0.05192084f,0.0f,0.0f,0.09007514f,0.0f,0.0f,0.025151148f,7.919698E-6f,0.0f,0.0018313112f,0.0145436f,0.054450806f,0.12797984f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.059141297f,0.020892957f,0.0f,0.098279655f,0.05828297f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.11039665f,0.0f,0.0f,0.0f,0.053336646f,0.0f,0.0f,0.08507843f,0.0f,0.0f,0.06554685f,0.009452949f,0.0f,0.007629284f,0.0f,0.028765898f,0.10263872f,0.041752808f,0.062005337f,0.044478178f,0.0f,0.0f,0.005904024f,8.8682055E-4f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0069284006f,0.066498056f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.05035396f,0.0f,0.12217615f,0.0f,0.119913526f,0.07956571f,0.12207263f,0.03218483f,0.0f,0.02710066f,0.022636268f,0.015647167f,0.0f,0.11522004f,0.0f,0.02771379f,0.0f,0.0f,0.0f,0.0f,0.029701354f,0.0f,0.0f,0.0f,0.0f,0.15132177f,0.0f,0.0f,0.0f,0.0f,0.0f,0.016040573f,0.0123390155f,0.0f,0.0f,0.0f,0.0f,0.05401499f,0.04475604f,0.0f,0.064246304f,0.0f,0.0f,0.0f,0.0f,0.1514622f,0.0037367684f,0.05236134f,0.12125185f,0.0f,0.0f,0.08529345f,0.0f,0.0f,0.0f,0.021191478f,0.0f,0.00896594f,0.1678437f,0.00846115f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.006917588f,0.022895483f,0.02009568f,0.0f,0.0f,0.0f,0.0f,0.02269956f,0.020049047f,0.0f,0.0f,0.0f,0.0f,0.0f,0.01585178f,0.098444566f,0.0f,0.052533984f,0.0f,0.05852503f,0.0f,0.0018540459f,0.0f,0.0f,0.012348213f,0.11396586f,0.0f,0.014174749f,0.0f,0.010799807f,0.0f,0.0f,0.012921698f,0.0f,0.0f,0.10583927f +// ) + + val vector = + floatArrayOf( + 0.015068196f,0.0f,0.0f,0.0f,0.0037743463f,0.0f,0.0f,0.07893528f,0.0f,0.0f,0.0f,0.0f,0.052832354f,0.0f,0.045785826f,0.0f,6.156802E-4f,0.04242764f,0.0f,0.0f,0.0f,0.0f,0.11469748f,0.13930011f,0.005731758f,0.03159248f,0.018799406f,0.028927676f,0.03472497f,0.01896616f,0.078822434f,0.0f,0.015187703f,0.0f,0.033177234f,0.07078301f,0.0f,0.0f,0.012238876f,0.0f,0.0f,0.0f,0.0f,0.0f,0.10691055f,0.008628067f,0.0f,0.0f,0.0f,0.0f,0.0f,0.06886323f,0.0f,0.0f,0.10460233f,0.0f,0.0f,0.0f,0.0f,0.0f,0.012850592f,0.0f,0.0f,0.103946045f,0.0f,0.018065454f,0.046292588f,0.063853905f,0.0f,0.10074362f,0.110680245f,0.10660499f,0.0f,0.06775707f,0.0f,0.0f,0.0f,0.0f,0.01639176f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.024850294f,0.0f,0.05308442f,0.0f,0.0f,0.0f,0.028708044f,0.02787582f,0.0f,0.0f,0.0f,0.0f,0.0f,0.027483912f,0.11719905f,0.04781422f,0.09033941f,0.09655397f,0.0032244714f,0.0f,0.0f,0.09580024f,0.07075415f,0.0876085f,0.0f,0.08756652f,2.2919098E-4f,0.019845076f,0.0f,0.0f,0.0f,0.04727701f,0.007276267f,0.0f,0.12660357f,0.03222255f,0.00182945f,0.0f,0.0f,0.0f,0.0f,0.0f,0.09080463f,0.0043369643f,0.0f,0.0f,0.0f,0.0f,0.0f,0.073994264f,0.0f,0.030294247f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.04890032f,0.0f,0.05318369f,0.0f,0.0f,0.0510094f,0.0f,0.0f,0.0f,0.12696978f,0.0f,0.21870367f,0.0f,0.0f,0.0f,0.0f,0.022256335f,0.13343737f,0.0f,0.0f,0.0f,0.0f,0.025192281f,0.1621841f,0.031685397f,0.0f,0.0f,0.03057069f,0.011333849f,0.0f,0.0f,0.11482361f,0.10645431f,0.0f,0.0f,0.0f,0.039949007f,0.0f,0.018850718f,0.0f,0.0f,0.0f,0.026081126f,0.0f,0.07934742f,0.0f,0.0f,0.0f,0.0f,0.0f,0.007998445f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.098366655f,0.0f,0.01606297f,0.16557153f,0.0f,0.0f,0.0f,0.0f,0.042638786f,0.024310581f,0.0f,0.027677892f,5.940642E-4f,0.0f,0.0f,0.0f,0.0f,0.05605889f,0.0f,0.0f,0.05216231f,0.080610394f,0.0f,0.0f,0.0f,0.0f,0.0f,0.07294793f,0.0f,0.02029506f,0.0f,0.0f,0.0f,0.12797904f,0.16668096f,0.083295606f,0.07768397f,0.07725612f,0.0f,0.0f,0.07259326f,0.110221304f,0.0f,0.0f,0.0f,0.0f,0.0f,0.027140126f,0.0f,0.053474665f,0.0f,0.018286237f,0.0f,0.0f,0.12152021f,0.0f,0.0f,0.0822232f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.04146023f,0.0f,0.034810524f,0.0f,0.00393797f,0.0f,0.032150663f,0.0f,0.0f,0.0f,0.0f,0.097777024f,0.0f,0.0f,0.0f,0.078797914f,0.0f,0.1292709f,0.0f,0.010623558f,0.0f,0.08360209f,0.0f,0.0f,0.122683614f,0.0f,0.0f,0.0f,0.0f,0.10111214f,0.10537941f,0.0f,0.0f,0.0f,0.0f,0.06272928f,0.0f,0.029668529f,0.049171254f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.032665383f,0.0f,0.0f,0.044802308f,0.0f,0.0f,0.05388319f,0.0f,0.0f,0.079517856f,0.012373011f,0.0f,0.01629987f,0.014890053f,0.0f,0.027798127f,0.0f,0.051028676f,0.15331483f,0.024111472f,0.0f,0.0f,0.0f,0.0f,0.0f,0.013699274f,0.0f,0.0f,0.07011116f,0.03022409f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.10939847f,0.0f,0.0f,0.0f,0.030306451f,0.0f,0.0f,0.12335773f,0.0f,0.0f,0.09099765f,0.0f,0.0f,0.0073862355f,0.0f,0.027847463f,0.0840776f,0.04207977f,0.046206567f,0.06679146f,0.0f,0.0f,0.01625976f,0.022998374f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.059722353f,0.0f,0.012246756f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.04984296f,0.0f,0.1435546f,0.0f,0.14667304f,0.079418436f,0.1305641f,0.014777453f,0.0f,0.020115053f,0.05619832f,0.011520876f,0.0f,0.11993748f,0.009492612f,0.019984039f,0.0f,0.0f,0.0f,0.0f,0.043548502f,0.0f,0.0f,0.0f,0.0f,0.15310751f,0.0f,0.0f,0.0f,0.0f,0.0f,0.018038996f,0.0021733972f,0.0f,0.0f,0.0f,0.0f,0.060995787f,0.06326715f,0.0f,0.06896745f,0.013745607f,5.018817E-4f,0.0f,0.0f,0.14184067f,0.019447664f,0.047488734f,0.13301876f,0.0f,0.0f,0.06715185f,0.0f,0.0f,0.0025059544f,0.0013816518f,0.0f,0.00415278f,0.17231767f,0.0073697185f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0017814273f,0.040113796f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.016738398f,0.0f,0.10465313f,0.0f,0.057283692f,0.0f,0.05406501f,0.0f,0.012632326f,0.0f,0.0f,0.0f,0.10440692f,0.0f,0.0047152108f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.11544036f + ) + val vector2 = floatArrayOf( + 0.029274145f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.04849013f,0.0f,0.0f,0.0030461443f,0.0f,0.04333778f,0.0f,0.036458552f,0.0f,0.0f,0.032146808f,0.0f,0.0f,0.0f,0.0f,0.12563168f,0.16337962f,0.0086008925f,0.028651662f,0.05676712f,0.038951095f,0.035215054f,0.023515426f,0.09426005f,0.0f,0.0f,0.0f,0.019520408f,0.09774056f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.12273409f,0.03317896f,0.0f,0.0f,0.0f,0.0f,0.0f,0.056036845f,0.0f,0.005601604f,0.09232295f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.10639726f,0.017117623f,0.0f,0.04106111f,0.06582154f,0.0f,0.10570599f,0.10395363f,0.11154216f,0.0f,0.09019618f,0.0f,0.0f,0.0f,0.0f,0.008780864f,0.0f,0.0f,0.01997713f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.016066022f,0.020096382f,0.0f,0.05578338f,0.0f,0.0f,0.0f,0.048834037f,0.031760734f,0.0f,0.0f,0.0f,0.0f,0.0f,0.02459963f,0.11993096f,0.047805987f,0.070974134f,0.10536186f,0.0f,0.0f,0.0f,0.111894555f,0.08973926f,0.071053386f,0.0f,0.071883f,0.005135076f,0.0f,0.0f,0.0f,0.0f,0.023139987f,0.027882056f,0.0f,0.12620124f,0.05076331f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.06944067f,0.0146693f,0.0f,0.0f,0.0f,0.0f,0.00978479f,0.04965295f,0.0f,0.03953311f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.05496083f,0.0f,0.05957852f,0.0f,0.0f,0.05285405f,0.0f,0.0f,0.0f,0.10977843f,0.0f,0.21329264f,0.0f,0.0f,0.0f,0.0f,0.022029493f,0.12511873f,0.0f,0.0f,0.0f,0.0f,0.015391711f,0.1697028f,0.035269253f,0.0f,0.0f,0.0070471396f,0.0f,0.0f,0.0f,0.123943165f,0.10272677f,0.0f,0.0f,0.0f,0.06351426f,0.0f,0.009808158f,0.0f,0.0f,0.0f,0.02582221f,0.0f,0.0745801f,0.0f,0.0f,0.023285847f,0.0f,0.0f,0.017162288f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.09181752f,0.0f,0.007880242f,0.15574618f,0.0f,0.0f,0.0f,0.0f,0.02478441f,0.039601766f,0.0f,0.049401764f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0793202f,0.0f,0.0f,0.071133174f,0.09675928f,0.0f,0.015621623f,0.0f,0.0f,0.0f,0.08347399f,0.009147923f,0.0f,0.0f,0.0f,0.0f,0.14187747f,0.15219086f,0.12055488f,0.07175866f,0.07192898f,0.0f,0.0f,0.04634941f,0.12534219f,0.0f,0.0f,0.0f,0.008665879f,0.0f,0.040081337f,0.0f,0.06729515f,0.0f,0.058273762f,0.0020215393f,0.0f,0.10878004f,0.0f,0.0f,0.09762441f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.03849448f,0.0f,0.03300536f,0.0f,0.0f,0.013231625f,0.018584426f,0.0f,0.0f,0.0f,0.0f,0.08124468f,0.0f,0.0f,0.0f,0.060708806f,0.0f,0.11115098f,0.0f,0.0f,0.0f,0.0803424f,0.0f,0.0f,0.115781434f,0.0f,0.00764197f,0.0f,0.0f,0.121340856f,0.0869794f,0.0f,0.0f,0.0f,0.0f,0.045324527f,0.0f,0.015057986f,0.048937548f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.030864827f,0.0f,0.0029875587f,0.03196471f,0.0f,0.0f,0.054534424f,0.0f,0.0f,0.07863297f,0.019617077f,0.0f,0.026181744f,0.0f,0.0f,0.021914937f,0.0f,0.063720085f,0.16607703f,0.006567324f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0017898319f,0.0f,0.0f,0.04841979f,0.0044351136f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.15329078f,0.0f,0.0f,0.0f,0.030429695f,0.0f,0.0f,0.11840538f,0.0f,0.0f,0.107368395f,0.014730752f,0.0f,0.0f,0.0f,0.030180579f,0.039591953f,0.03209204f,0.048180148f,0.0676186f,0.0f,0.0f,0.03614289f,0.030257396f,1.5626202E-4f,0.018185573f,0.0f,0.0f,0.0f,0.0f,0.055325508f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.051894154f,0.0f,0.12869093f,0.0f,0.122797504f,0.083724305f,0.12840301f,0.0f,0.0f,0.0f,0.05686797f,0.0f,0.0f,0.11015593f,0.018203156f,0.020094728f,0.0f,0.0f,0.0f,0.0f,0.058597155f,0.0f,0.0f,0.0f,0.0f,0.12797132f,0.0f,0.006606713f,0.0f,0.0f,0.0f,0.028628595f,0.0f,0.0f,0.0f,0.0f,0.0f,0.050383586f,0.07132696f,0.0f,0.092209496f,0.0f,0.0f,0.0f,0.0f,0.14604862f,0.01660271f,0.057229653f,0.13104743f,0.0f,0.0f,0.06136706f,0.0f,0.0f,0.0f,0.0011910667f,0.0f,0.0f,0.15921566f,0.0f,0.0f,0.0f,0.0f,0.007558685f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.007532647f,0.05110198f,0.00667856f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0016389234f,0.0f,0.0f,0.0f,0.0f,0.018518167f,0.0f,0.08580791f,0.0f,0.06099585f,0.0f,0.0366169f,0.0f,0.0f,0.0f,0.0f,0.0f,0.073218584f,0.0f,0.0f,0.0f,0.008933658f,0.0f,0.0f,0.0f,0.0f,0.0f,0.116691895f + ) + + val similarity = VectorSimilarityCalculator.cosineSimilarity(vector, vector2) + println("vectorSimilarity-余弦相似度:$similarity") + val similarity2 = VectorSimilarityCalculator.euclideanDistance(vector, vector2) + println("vectorSimilarity-欧氏距离:$similarity2") + val similarity3 = VectorSimilarityCalculator.normalizedEuclideanDistance(vector, vector2) + println("vectorSimilarity-归一化欧氏距离:$similarity3") + } } \ No newline at end of file diff --git a/app/src/test/java/com/sw/inbound/VectorSimilarityCalculator.kt b/app/src/test/java/com/sw/inbound/VectorSimilarityCalculator.kt new file mode 100644 index 0000000..7381eed --- /dev/null +++ b/app/src/test/java/com/sw/inbound/VectorSimilarityCalculator.kt @@ -0,0 +1,65 @@ +package com.sw.inbound + +import kotlin.math.abs +import kotlin.math.sqrt + +object VectorSimilarityCalculator { + + /** + * 计算两个向量的余弦相似度 + * @param vec1 向量1 + * @param vec2 向量2 + * @return 相似度值(-1~1),向量长度不一致返回0 + */ + fun cosineSimilarity(vec1: FloatArray, vec2: FloatArray): Float { + if (vec1.size != vec2.size) return 0f + + var dotProduct = 0f // 点积 + var norm1 = 0f // 向量1的模长 + var norm2 = 0f // 向量2的模长 + + for (i in vec1.indices) { + dotProduct += vec1[i] * vec2[i] + norm1 += vec1[i] * vec1[i] + norm2 += vec2[i] * vec2[i] + } + + // 避免除以0 + if (norm1 == 0f || norm2 == 0f) return 0f + + return dotProduct / (sqrt(norm1.toDouble()) * sqrt(norm2.toDouble())).toFloat() + } + + /** + * 计算两个向量的欧氏距离(值越小越相似) + * @param vec1 向量1 + * @param vec2 向量2 + * @return 欧氏距离,向量长度不一致返回Float.MAX_VALUE + */ + fun euclideanDistance(vec1: FloatArray, vec2: FloatArray): Float { + if (vec1.size != vec2.size) return Float.MAX_VALUE + + var sum = 0f + for (i in vec1.indices) { + val diff = vec1[i] - vec2[i] + sum += diff * diff + } + return sqrt(sum.toDouble()).toFloat() + } + + /** + * 归一化欧氏距离(0~1,值越小越相似) + */ + fun normalizedEuclideanDistance(vec1: FloatArray, vec2: FloatArray): Float { + val distance = euclideanDistance(vec1, vec2) + if (distance == Float.MAX_VALUE) return 1f + + // 计算向量最大值差(归一化分母) + var maxDiff = 0f + for (i in vec1.indices) { + val diff = abs(vec1[i] - vec2[i]) + if (diff > maxDiff) maxDiff = diff + } + return if (maxDiff == 0f) 0f else distance / (maxDiff * vec1.size) + } +} \ No newline at end of file