Hope you are fine what I am trying to achieve is to get all the duplications from the internal storage, for that, I am already using a method I don't know what I am doing wrong please have a look,
private fun getDuplicateItems() {
var tempDuplicateItem: DuplicateItemModel
GlobalScope.launch(Dispatchers.IO) {
for (i in 0 until listOfAllFiles.size) {
for (j in i until listOfAllFiles.size) {
if(!File(listOfAllFiles[i].directoryPath).isDirectory && !File(listOfAllFiles[j].directoryPath).isDirectory ){
if (listOfAllFiles[i].fileName == listOfAllFiles[j].fileName && listOfAllFiles[i].fileSize == listOfAllFiles[j].fileSize &&
!listOfAllFiles[i].fileName.endsWith(".tmp") && !listOfAllFiles[j].fileName.endsWith(".tmp") &&
!listOfAllFiles[i].fileName.endsWith(".chck") && !listOfAllFiles[j].fileName.endsWith(".chck") &&
!listOfAllFiles[i].fileName.startsWith(".") && !listOfAllFiles[j].fileName.startsWith(".")
) {
tempDuplicateItem = DuplicateItemModel(
"$i${listOfAllFiles[i].fileName}",
listOfAllFiles[i].fileName,
listOfAllFiles[i].absolutePath,
listOfAllFiles[i].fileModificationDateAndTime,
File(listOfAllFiles[i].directoryPath).length(),
false,
false,
)
tempArrayListOfDuplicateItemsSingle.add(
DuplicateItemModel(
"$i${listOfAllFiles[i].fileName}",
listOfAllFiles[j].fileName,
listOfAllFiles[j].absolutePath,
listOfAllFiles[j].fileModificationDateAndTime,
File(listOfAllFiles[j].directoryPath).length(),
true,
true,
)
)
tempArrayListOfDuplicateItems.add(
DuplicateItemArrayListItem(
tempDuplicateItem,
tempArrayListOfDuplicateItemsSingle
)
)
}
}
}
}
}.invokeOnCompletion {
var tempTotalDuplicateSize: Double = 0.0
GlobalScope.launch(Dispatchers.Main) {
progressBarDuplicateFiles.visibility = View.INVISIBLE
imageViewNextDuplicateFiles.visibility = View.VISIBLE
for (x in 0 until tempArrayListOfDuplicateItems.size) {
tempArrayListOfDuplicateItems[x].listOfDuplicationSubItems.forEach { duplicateItem ->
tempTotalDuplicateSize += duplicateItem.fileSize
}
}
//UI Stuff
textViewTotalSizeOfDuplications.text = "total Size of Duplicate Files (${HelperClass.readableFileSize(tempTotalDuplicateSize.toLong())})"
textViewTotalFolderFilesDuplicateItem.text = "${tempArrayListOfDuplicateItems.size} Item(s)"
relativeLayoutDuplicateItem.isClickable = true
}
}
}
I am using MediaLoader, a library which gives me all the files on internal storage, and through those files, I am checking the data if the data is equal or not but getting the stream of data which I don't know is correct or not,
This should help you get started:
File f = new File("your_relevant_path");
File[] files = f.listFiles();
HashSet<String> mHashSet = new HashSet<>();
for (File currFile :
files) {
if (!mHashSet.add(currFile.getName()))
{
// Here there is a duplication of a file
}
}
Related
I am fairly new to Android + Kotlin, however I am wondering if there is a faster way to read a text (.pgn) file and mark pointers to places in the file for later reference.
At the moment I am using RandomAccessFile however it is incredible slow for a process that should be extremely quick.
This is my code at the moment:
private fun loadPGN() {
try {
val selectedPGN = File((context as MainActivity).filesDir, "mygames.pgn")
val raf = RandomAccessFile(selectedPGN, "r")
val length = raf.length()
raf.seek(0)
charPosition = raf.filePointer
while (charPosition < length) {
val str : String = raf.readLine()
if (str.contains("[Event ")) {
mutableListEvent += charPosition
findMoves = true
}
if (findMoves && ((str.startsWith(str.filter { it.isDigit() }) && !str.startsWith("[")) || str.startsWith("{ "))) {
mutableListMoves += charPosition
findMoves = false
}
charPosition = raf.filePointer
}
for (i in 0 until mutableListEvent.size) {
val event = if (mutableListEvent[i] != mutableListEvent[mutableListEvent.size - 1]) mutableListEvent[i + 1] else length
val moves = mutableListMoves[i]
raf.seek(mutableListEvent[i])
eventStr = raf.readLine().removeRange(0,8).replace("\"]", "")
eventMutableList.add(eventStr)
difference += (event - moves)
headerLength += (mutableListMoves[i] - mutableListEvent[i])
raf.seek(moves)
val byteArray = ByteArray(difference[i].toInt())
raf.readFully(byteArray)
val string = String(byteArray)
var stringEdited = String(byteArray).replace("\n","")
if (stringEdited.contains("{[")) {
val re = "\\{\\[.*?]}".toRegex()
stringEdited = re.replace(stringEdited,"")
}
gamePlayMutableList.add(string)
}
// Header Information
for (i in 0 until headerLength.size) {
raf.seek(mutableListEvent[i])
charPosition = raf.filePointer
while (charPosition < mutableListMoves[i]) {
val str = raf.readLine()
if (str.contains("[Site \"") || str.contains("[Date \"") || str.contains("[Round \"") || str.contains("[White \"") || str.contains(
"[Black \""
) || str.contains("[Result \"") || str.contains("[EventDate \"") || str.contains("[PlyCount \"")
) {
if (str.contains("[Site \"")) {
siteMutableList += str.replace("[Site \"", "").replace("\"]", "")
}
if (str.contains("[Date \"")) {
dateMutableList += str.replace("[Date \"", "").replace("\"]", "")
}
if (str.contains("[Round \"")) {
roundMutableList += str.replace("[Round \"", "").replace("\"]", "")
}
if (str.contains("[White \"")) {
whiteMutableList += str.replace("[White \"", "").replace("\"]", "")
}
if (str.contains("[Black \"")) {
blackMutableList += str.replace("[Black \"", "").replace("\"]", "")
}
if (str.contains("[Result \"")) {
resultMutableList += str.replace("[Result \"", "").replace("\"]", "")
}
if (str.contains("[EventDate \"")) {
eventDateMutableList += str
}
if (str.contains("[PlyCount \"")) {
plyCountMutableList += str
}
}
charPosition = raf.filePointer
}
}
} catch (e: IOException) {
e.printStackTrace()
}
}
}
Once I have the pointers, I then load the information in a recycler view so as you're able to select which game (with information visible) you wish.
I have crawled stack overflow regarding this, however the majority of questions are just to read a whole text file and return that, not put pointers into places for reference
So I managed to figure out the 'issues' regarding this. raf.readLine() is EXTREMELY slow. This is a known problem, but not really talked about so much. Anyway I now use .readFully(), which is substantially faster.
Im followed a tutorial to create a maze with Recursive Backtracking and it works great.
Im trying to create a game where people get on the same maze, and if someone wins, it creates a new maze and everyones current maze gets updated.
So what i was thinking is to have a seed to create the same maze and pass that seed to all the players so they can have the same maze.
Is there a way to modify it so i can give the maze a seed and it creates always the same maze?
This is what i have now:
It uses a Cell class (posx,posy)
class Cell(var col:Int = 0, var row: Int = 0){
var topWall = true
var leftWall = true
var bottomWall = true
var rightWall = true
var visited = false
}
fun createMaze(){
var stack = Stack<Cell>()
var current:Cell
var next:Cell?
for(x in 0 until COLS){
for(y in 0 until ROWS){
cells[x][y] = Cell(x,y)
}
}
player = cells[0][0]
exit = cells [COLS-1][ROWS-1]
current = cells[0][0]
current.visited = true
do{
next = getNeighbour(current)
if(next != null) {
removeWall(current, next)
stack.push(current)
current = next
current.visited = true
}else{
current = stack.pop()
}
}while (!stack.empty())
}
fun getNeighbour(cell:Cell): Cell? {
var vecinos: ArrayList<Cell> = ArrayList()
//vecino izquierda
if(cell.col > 0) {
if (!cells[cell.col - 1][cell.row].visited) {
vecinos.add(cells[cell.col - 1][cell.row])
}
}
//vecino derecha
if(cell.col < COLS - 1) {
if (!cells[cell.col + 1][cell.row].visited) {
vecinos.add(cells[cell.col + 1][cell.row])
}
}
//vecino arriba
if(cell.row > 0) {
if (!cells[cell.col][cell.row - 1].visited) {
vecinos.add(cells[cell.col ][cell.row - 1])
}
}
//vecino abajo
if(cell.row < ROWS - 1) {
if (!cells[cell.col][cell.row + 1].visited) {
vecinos.add(cells[cell.col][cell.row + 1])
}
}
if (vecinos.size > 0) {
var index = random.nextInt(vecinos.size)
return vecinos[index]
}else {
return null
}
}
fun removeWall(current:Cell,next:Cell){
if (current.col == next.col && current.row == next.row +1){
current.topWall = false
next.bottomWall = false
}
if (current.col == next.col && current.row == next.row -1){
current.bottomWall = false
next.topWall = false
}
if (current.col == next.col + 1 && current.row == next.row){
current.leftWall = false
next.rightWall = false
}
if (current.col == next.col - 1 && current.row == next.row){
current.rightWall = false
next.leftWall = false
}
}
If you want to pass a seed to create the maze, then you have to make sure that all of the players are using the same random number generator. Which means you have to supply your own random number generator implementation.
The application would seed the random number generator with the value you pass, and then it should deterministically generate the same sequence of random numbers for each client.
Note also that you can't ever change the random number generator implementation unless you can prove that the new implementation will generate exactly the same sequence of numbers that the original did.
when I add multiple loop to retrieve data from firebase only the first loop works, why is that happening and how can I make all the loops work
val children = dataSnapshot!!.children
children.forEach {
if( it.child("Date").getValue().toString().equals(Data.date) && it.child("Time").getValue().toString().equals(Data.time) && it.child("location").getValue().toString().equals(items.get(0).toString())){
//
}
}
children.forEach {
if( it.child("Date").getValue().toString().equals(Data.date) && it.child("Time").getValue().toString().equals(Data.time) && it.child("location").getValue().toString().equals(items.get(1).toString())){
//
}
}
children.forEach {
if( it.child("Date").getValue().toString().equals(Data.date) && it.child("Time").getValue().toString().equals(Data.time) && it.child("location").getValue().toString().equals(items.get(2).toString())){
//
}
}
At first glance the 3 loops look identical, but they differ at the last 3d of the condition. Each one checks this:
it.child("location").getValue().toString().equals(items.get(x).toString())
where x is 0, 1 or 2.
So they are not the same as to be surprised why the last 2 don't work as you say.
Maybe the condition works only for:
items.get(0).toString()
Anyway you can simplify your code and add some debugging code so to be sure what's happening:
(0..2).forEach { i ->
children.forEach {
val dateOk = it.child("Date").getValue().toString().equals(Data.date)
val timeOk = it.child("Time").getValue().toString().equals(Data.time)
val itemOk = it.child("location").getValue().toString().equals(items.get(i).toString())
Log.d("Loop", "at $i: dateOk = $dateOk, timeOk = $timeOk, itemOk = $itemOk")
if( dateOk && timeOk && itemOk){
when (i) {
0 -> //
1 -> //
2 -> //
}
}
}
}
I'm using mapbox, with GeoJsonSource and symbollayer. When user clicks on feature it should change a color. I handle this logic with following code and it works, but it is too slow and takes several second to change icon color.
Here I configure symbol layer, add icon changelogic for 'PROPERTY_SELECTED':
mapBoxMap?.addLayer(SymbolLayer(markerStyleLayerIdentifier, markerSourceIdentifier)
.withProperties(
PropertyFactory.iconImage(markerImage),
PropertyFactory.iconAllowOverlap(false),
PropertyFactory.iconImage(match(
get(PROPERTY_SELECTED), literal(0),
literal(markerImage),
literal(markerImageSelected)
))
))
on map click features objects are update:
override fun onMapClick(point: LatLng) {
val screenPoint = mapBoxMap?.projection?.toScreenLocation(point)
var features = mapBoxMap?.queryRenderedFeatures(screenPoint
?: return, markerStyleLayerIdentifier)
if ((features ?: return).isNotEmpty()) {
var feature = features[0]
showMarkerInfo(feature)
doAsync {
var featureList = featureCollection?.features()
var id = feature.getNumberProperty(PROPERTY_STOP_ID)
if (featureList != null) {
for (i in 0 until featureList.size) {
var fId = featureList[i].getNumberProperty(PROPERTY_STOP_ID)
if (fId == id) {
featureList[i].properties()?.addProperty(PROPERTY_SELECTED, 1)
} else {
featureList[i].properties()?.addProperty(PROPERTY_SELECTED, 0)
}
}
uiThread {
refreshSource()
}
}
}
}
}
and refresh source :
private fun refreshSource() {
var source = mapBoxMap?.getSource(markerSourceIdentifier) as GeoJsonSource?
if (source != null && featureCollection != null) {
source.setGeoJson(featureCollection)
}
}
after 'refreshSource' is called , it takes several time before icon update. In my case there are 2050 features is source. Is there any better way to implement it ? Or any way to optimise this solution ?
here is a second , faster way from github answer:
var selectedLayer = mapBoxMap?.getLayer(markerSelectedStyleLayerIdentifier) as SymbolLayer?
var id = feature.getNumberProperty(PROPERTY_STOP_ID)
var selectedExpression = any(
eq(get(PROPERTY_STOP_ID), literal(id.toString()))
)
selectedLayer?.filter = selectedExpression
you can see whole issue there
https://github.com/mapbox/mapbox-java/issues/892
This is my code, in which I am adding data to a list:
fun bindProcess(listOfDocId: MutableList<String>, isActvityLogEnabled: Boolean): Observable<MutableList<SearchResultModel>> {
return Observable.create<MutableList<SearchResultModel>> {
var filteredList =CopyOnWriteArrayList<SearchResultModel>()// mutableListOf<SearchResultModel>()
val headerItem: SearchResultModel = SearchResultModel()
headerItem.type = 0
headerItem.title = context.getString(R.string.top_matches_label)
filteredList.add(headerItem)
for (row in ContSyncApplication.getContacts()) {
if (listOfDocId.contains(row.docId)) {
val myData: SearchResultModel = SearchResultModel()
myData.type = 1
myData.docId = row.docId
myData.name = row.display_name
if (!row.profile_image.isNullOrBlank()) {
myData.imagePath = row.profile_image!!
}
filteredList.add(myData)
if (isActvityLogEnabled && DatabaseQueryHelper.checkActivityLogById(row.docId)) {
val myactivityData: SearchResultModel = SearchResultModel()
myactivityData.type = 1
myactivityData.docId = row.docId
myactivityData.name = row.display_name
myactivityData.imagePath = row.profile_image ?: ""
mActvityList.add(myactivityData)
}
}
}
if (mActvityList.size > 0) {
val activityHeader: SearchResultModel = SearchResultModel()
activityHeader.type = 0
activityHeader.title = "Activity Log"
filteredList.add(activityHeader)
filteredList.addAll(mActvityList)
}
it.onNext(filteredList)
it.onComplete()
}
}
While I execute and add data in the list I am getting a ConcurrentModificationException. Can anyone suggest to me how to execute the loop so that I can fix this issue? I have to search and add to the list.
Check if you are modifying same collection while traversing using for each. If you want to modified same collection you need to use iterator.
val tempList = arrayListOf<MyObject>()
tempList.addAll(currentList)
currentList.forEach {
if (condition to remove here) {
tempList.remove(it)
}
}
currentList = tempList