Monday 28 February 2022

Unable to record from USB microphone on Chrome on Android (Lollipop)

Based on previous thread, getUserMedia is supported in Chrome on Android now (version 40).

I got this working using the usual getUserMedia idiom (see, for example, http://www.html5rocks.com/en/tutorials/getusermedia/intro/). This works on desktop (any mic) and on mobile (default mic).

However, when a USB mic is plugged in, this does not seem to work. The usual permission dialog is shown. However, the input audio will actually come from the phone's default mic (ie, scratching/tapping the usb mic produced no noise), even though the USBmic is clearly connected (ie, it lit up).

On desktop, you can fix this by selecting the audio input source, but I'm not sure how to do that on Android.

The really funny thing is that typical audio recording APPs can actually CORRECTLY get the audio input from the USB mic on the same device.

Has anyone experienced this problem?



from Unable to record from USB microphone on Chrome on Android (Lollipop)

ErrnoException: open failed: ENOENT (No such file or directory) in android

I am simply writing into a file that is created in internal storage. It's working fine on most of the devices but strangely it's not working on a few devices.

I am using all three permissions:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="30"/>
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
        android:minSdkVersion="30"/>

Below is my code part for writing into file:

val oldfile = File(oldBasePath)
val fiStream = FileInputStream(oldfile)
var outputFile = File(appFolder, fileName)
var fos = FileOutputStream(outputFile)
val buf = ByteArray(1024)
var len: Int
    do {
           len = fiStream.read(buf)
           if (len > 0) {
                  fos?.write(buf, 0, len)
                 } else {
                     break
                  }
                 } while (true)

                fiStream.close()
                fos?.close()

Here I am getting error in 2nd line of code. Below is the logcat:

Non-fatal Exception: java.lang.Exception: java.io.FileNotFoundException: /data/app/~~g6QIOWSCR57wvCe1sS-znA==/com.whatsapp-UV9OLmiceKxlpMCN9VkZ0A==/base.apk: open failed: ENOENT (No such file or directory)
       at com.test.helpers.Applog.e(Applog.kt:22)
       at com.test.ui.FileListFragment.catchErrorFromSaveApk(FileListFragment.kt:413)
       at com.test.ui.FileListFragment.saveApkApps(FileListFragment.kt:388)
       at com.test.ui.FileListFragment.access$getSessionManager$p(FileListFragment.kt:35)
       at com.test.ui.FileListFragment$loadAppFiles$1$result1$1.invokeSuspend(FileListFragment.kt:191)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
       at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)


Caused by android.system.ErrnoException: open failed: ENOENT (No such file or directory)
       at libcore.io.Linux.open(Linux.java)
       at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
       at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254)
       at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
       at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:8517)
       at libcore.io.IoBridge.open(IoBridge.java:478)
       at java.io.FileInputStream.<init>(FileInputStream.java:160)
       at com.test.ui.FileListFragment.saveApkApps(FileListFragment.kt:359)
       at com.test.ui.FileListFragment.access$getSessionManager$p(FileListFragment.kt:35)
       at com.test.ui.FileListFragment$loadAppFiles$1$result1$1.invokeSuspend(FileListFragment.kt:191)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
       at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
       at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)


from ErrnoException: open failed: ENOENT (No such file or directory) in android

View vs Composable

In the view World we can just use View.draw(canvus) to draw view on our Canvus (which might be connected to bitmap). But here in compose how can we achieve the same.

We have a draw modifier but it has no method draw(canvus)



from View vs Composable

Color certain grid tiles based on coordinates

I would like to color certain grid tiles based on their coordinates.

I created the following grid:

<!DOCTYPE html>
<html>

<head>
    <title>Color Tiles</title>
    <meta charset="utf-8" />
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.1/dist/leaflet.css" />

    <style>
        body {
            padding: 0;
            margin: 0;
        }

        html,
        body,
        #map {
            height: 100%;
            width: 100%;
        }
    </style>
</head>

<body>

  <div id="map"></div>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
    <script src="https://unpkg.com/leaflet@1.0.1/dist/leaflet.js"></script>

    <!-- Make sure you put this AFtER leaflet.js, when using with leaflet 
    <script src="https://unpkg.com/leaflet-geosearch@3.0.0/dist/geosearch.umd.js"></script>
    -->

    <script>
        var map = new L.Map('map', { center: [10, 0], zoom: 2 });

        let zoomLevel = map.getZoom()
        console.log("zoomLevel " + zoomLevel)

        // if(zoomLevel === 1) {
            var tiles = new L.GridLayer();
            tiles.createTile = function (coords) {
                var tile = L.DomUtil.create('canvas', 'leaflet-tile');
                var ctx = tile.getContext('2d');
                var size = this.getTileSize()
                // console.log("size: " + size.toString())
                tile.width = size.x
                tile.height = size.y

                // calculate projection coordinates of top left tile pixel
                var nwPoint = coords.scaleBy(size)

                // calculate geographic coordinates of top left tile pixel
                var nw = map.unproject(nwPoint, coords.z)

                ctx.fillStyle = 'white';
                ctx.fillRect(0, 0, size.x, 50);
                ctx.fillStyle = 'black';
                ctx.fillText('x: ' + coords.x + ', y: ' + coords.y + ', zoom: ' + coords.z, 20, 20);
                ctx.fillText('lat: ' + nw.lat + ', lon: ' + nw.lng, 20, 40);
                ctx.strokeStyle = 'black';
                ctx.beginPath();
                ctx.moveTo(0, 0);
                ctx.lineTo(size.x - 1, 0);
                ctx.lineTo(size.x - 1, size.y - 1);
                ctx.lineTo(0, size.y - 1);
                ctx.closePath();
                ctx.stroke();
                return tile;
            }

            L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
                attribution: 'Map data &copy; <a href="http://www.osm.org">OpenStreetMap</a>',
            }).addTo(map)

            tiles.addTo(map)
    
    </script>
</body>

</html>

I would like to have the following:

enter image description here

I tried to style it directly via css, which seems to work. However, I would like to style it based on the provided coordinates.

Any suggestion how to do this?



from Color certain grid tiles based on coordinates

Show fixed 100 m x 100 m grid on lowest zoom level

I am using leaflet with openstreetmap to create a fixed grid on top of the world map that consists of 100m x 100m tiles. Basically, I am creating a turn-based game, where a player should be able to click on a certain tile, which then reveals a context menu. The server is going to know that the player has opened the tile for a certain place.

I tried the following:

<!DOCTYPE html>
<html>

<head>
    <title>GridLayer Test</title>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.1/dist/leaflet.css" />
    <style>
        body {
            padding: 0;
            margin: 0;
        }

        html,
        body,
        #map {
            height: 100%;
            width: 100%;
        }
    </style>
</head>

<body>
    <div id="map"></div>

    <script src="https://unpkg.com/leaflet@1.0.1/dist/leaflet.js"></script>

    <script>
        var map = new L.Map('map', { center: [10, 0], zoom: 2 });

        var tiles = new L.GridLayer();
        tiles.createTile = function (coords) {
            var tile = L.DomUtil.create('canvas', 'leaflet-tile');
            var ctx = tile.getContext('2d');
            var size = this.getTileSize()
            tile.width = size.x
            tile.height = size.y

            // calculate projection coordinates of top left tile pixel
            var nwPoint = coords.scaleBy(size)

            // calculate geographic coordinates of top left tile pixel
            var nw = map.unproject(nwPoint, coords.z)

            ctx.fillStyle = 'white';
            ctx.fillRect(0, 0, size.x, 50);
            ctx.fillStyle = 'black';
            ctx.fillText('x: ' + coords.x + ', y: ' + coords.y + ', zoom: ' + coords.z, 20, 20);
            ctx.fillText('lat: ' + nw.lat + ', lon: ' + nw.lng, 20, 40);
            ctx.strokeStyle = 'red';
            ctx.beginPath();
            ctx.moveTo(0, 0);
            ctx.lineTo(size.x - 1, 0);
            ctx.lineTo(size.x - 1, size.y - 1);
            ctx.lineTo(0, size.y - 1);
            ctx.closePath();
            ctx.stroke();
            return tile;
        }

        L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            attribution: 'Map data &copy; <a href="http://www.osm.org">OpenStreetMap</a>',
            minNativeZoom: 1,
            maxNativeZoom: 1,
        }).addTo(map)

        tiles.addTo(map)
    </script>
</body>

</html>

As you can see the grid changed when I zoom in or out, even though I used minNativeZoom. However, I would like to have the grid fixed and 100m x 100m wide.

I also tried to only return tile when zoomLevel = 18. This does not work.

Any suggestions what I am doing wrong?

I appreciate your replies!



from Show fixed 100 m x 100 m grid on lowest zoom level

Get current selection info from Froala editor

I am using Froala WYSIWYG editor in my project. I would like to create my own font-family select component which will display the current font-family. So I need to listen to changes of an editor's selection, each time get current font-family and update my custom component.

import "froala-editor/js/plugins/font_family.min.js";
import Froala from "froala-editor";

const editor = new Froala("#container", {
    events: {
        onSelectionChange: function() { // I need something like this.
            console.log(this.selection.get().fontFamily); // Eg. "Arial" or "Verdana". 
        }
    }
});

I only found fontFamilySelection option in the docs, however, it will show the current font family in a native editor's component. One way is to read the current font family from the native component, but it's not a very clean solution.

Is there any way to do something like this?



from Get current selection info from Froala editor

Sunday 27 February 2022

Issue found: Invalid Data safety section. How to fix this issue?

Issue found: Invalid Data safety section

Issue details

We found an issue in the following area(s):

SPLIT_BUNDLE 14: Policy Declaration for Play Safety Label: Device Or Other IDs Data Type - Device Or Other IDs (some common examples may include Advertising ID, Android ID, IMEI, BSSID)


from Issue found: Invalid Data safety section. How to fix this issue?

Saturday 26 February 2022

What is the difference between CSVLogger and model.evaluate()?

I have been using Keras/TF's CSVLogger in order to save the training and validation accuracies. Then I was plotting those data to check the trajectory of training and validation accuracy or loss.

Yesterday, I read this link.

Here, they used model.evaluate() to plot the accuracy metric.

What is the difference between these two approaches?



from What is the difference between CSVLogger and model.evaluate()?

Bing Visual Search API endpoint returns different results than bing.com/visualsearch

I'm trying to collect similar images of an image using Bing Visual Search API. I have the following code snippet and I'm supplying an insightsToken of this image to the API endpoint.


import requests
import json

BASE_URI = "https://api.bing.microsoft.com/v7.0/images/visualsearch"

SUBSCRIPTION_KEY = ''

HEADERS = {'Ocp-Apim-Subscription-Key': SUBSCRIPTION_KEY}

insightsToken = 'ccid_twIfDfmx*cp_BF680FB5127A96880FCA7D76CC402B60*mid_D6663701CA72F63CF255CBF7EB4998ED50CAABC8*simid_608045920540183139*thid_OIP.twIfDfmxxN4umi!_-sacdNAHaFo'

formData = '{"imageInfo":{"imageInsightsToken":"' + insightsToken + '", }, "knowledgeRequest":{"invokedSkills": ["SimilarImages"]}}'

file = {'knowledgeRequest': (None, formData)}

def main():

    try:
        response = requests.post(BASE_URI, headers=HEADERS, files=file)
        response.raise_for_status()
        print_json(response.json())

    except Exception as ex:
        raise ex


def print_json(obj):
    """Print the object as json"""
    print(json.dumps(obj, sort_keys=True, indent=2, separators=(',', ': ')))

Take a look at the first few images that bing.com/visualsearch shows for that image. I tried both uploading an image and providing a link of an image. The results were the identical.

enter image description here

Now take a look at the first few images that were collected with the code snippet via API endpoint.

enter image description here

For some reason, bing.com/visualsearch results are much better and precise than Bing Visual Search API. I know that Bing Image Search API has the market parameter (based on IP, and your cookies and browsing history). However, even when I tried to change my IP and use incognito mode in a browser, I still got identical results when using bing.com/visualsearch. I also tried to provide params = (('mkt', 'en-us')) to the API endpoint, but the results were still almost identical. So I think this parameter doesn't affect the outcome to such a large extent. So I don't supply anything, as I think this makes the result close to the web search.

Still, why are the results so different? Is Bing using one API version for their web search and another version for their cloud services?



from Bing Visual Search API endpoint returns different results than bing.com/visualsearch

ExoPlayer with Equalizer - sound too loud at start

I have an Android app, where music is being played using the ExoPlayer. I've added Equalizer functionality, but it seems that on some devices (Pixel 6, Huawei P40) there is an issue, when Equalizer is being enabled. When ExoPlayer is initialized and equalizer.setEnabled(true) is called, there is a very loud sound for a few miliseconds. Although it is very short, it seems that it is caused by increasing the volume of the particular stream significantly, until it's back to normal. When I tried to delay setEnabled(true) call for a few seconds, the issue was resolved, but this doesn't feel like correct approach.

Has anybody of you encountered this issue and solved it? I tried to enable the equalizer in different places (when instantiating the ExoPlayer instance, in onPlaybackStateChanged method, etc.), but the issue was always there.

Code:

exoPlayer = new ExoPlayer.Builder(context).build();
equalizer = new Equalizer(0, exoPlayer.getAudioSessionId());
equalizer.setEnabled(true);
// Bands and presets are set here
// ...
// exoplayer is prepared, listeners are added, etc.

I'm sure the issue is caused by Equalizer, because if the equalizer-related code is not called, or if equalizer.setEnabled() is called with false, everything is OK.



from ExoPlayer with Equalizer - sound too loud at start

BroadcastReceiver not receiving any activity recognition broadcast

My main activity registering broadcast for Activity Recognition but and don't see any calls to Broadcast Receiver's onReceive method. I am not able to figure out why it's not working as expected.

I am testing on Real device with android 11 (API 30) with all required permission

Main Activity Register Broadcast

List<ActivityTransition> transitions = new ArrayList<>();
        PendingIntent activityPendingIntent;


        // Action fired when transitions are triggered.
        final String TRANSITIONS_RECEIVER_ACTION = "com.example.TRANSITIONS_RECEIVER_ACTION";

        transitions.add(
                new ActivityTransition.Builder()
                        .setActivityType(DetectedActivity.IN_VEHICLE)
                        .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
                        .build());
        transitions.add(
                new ActivityTransition.Builder()
                        .setActivityType(DetectedActivity.IN_VEHICLE)
                        .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
                        .build());
        transitions.add(
                new ActivityTransition.Builder()
                        .setActivityType(DetectedActivity.WALKING)
                        .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
                        .build());
        transitions.add(
                new ActivityTransition.Builder()
                        .setActivityType(DetectedActivity.WALKING)
                        .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
                        .build());
        transitions.add(
                new ActivityTransition.Builder()
                        .setActivityType(DetectedActivity.STILL)
                        .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
                        .build());
        transitions.add(
                new ActivityTransition.Builder()
                        .setActivityType(DetectedActivity.STILL)
                        .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
                        .build());

        transitions.add(
                new ActivityTransition.Builder()
                        .setActivityType(DetectedActivity.ON_BICYCLE)
                        .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)

                        .build());
        transitions.add(
                new ActivityTransition.Builder()
                        .setActivityType(DetectedActivity.ON_BICYCLE)
                        .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
                        .build());

        transitions.add(
                new ActivityTransition.Builder()
                        .setActivityType(DetectedActivity.RUNNING)
                        .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER)
                        .build());

        transitions.add(
                new ActivityTransition.Builder()
                        .setActivityType(DetectedActivity.RUNNING)
                        .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
                        .build());


        ActivityTransitionRequest request = new ActivityTransitionRequest(transitions);
        Intent mintent = new Intent(this, ActivityRecognitionBroadcastReceiver.class);
        mintent.setAction(TRANSITIONS_RECEIVER_ACTION);

        activityPendingIntent = PendingIntent.getBroadcast(this,
                0,
                mintent,
                PendingIntent.FLAG_UPDATE_CURRENT);

        Task<Void> task = ActivityRecognition.getClient(this)
                .requestActivityTransitionUpdates(request, activityPendingIntent);


        task.addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(@NonNull Void command) {
                checkFirstimeActivityRecognition = false;
                Log.i(TAG, "Successfully added transition updates listener");
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Log.e(TAG,"Transitions could not be unregistered: " + e);
            }
        });
        ActivityRecognitionBroadcastReceiver broadcastReceiver = new ActivityRecognitionBroadcastReceiver();
        registerReceiver(broadcastReceiver, new IntentFilter(TRANSITIONS_RECEIVER_ACTION));
        Log.d(TAG, "setupActivityRecognition: Register Broadcast receiver ");

BroadcastReceiver

public class ActivityRecognitionBroadcastReceiver extends BroadcastReceiver {
    public static final String TAG = "Broadcast Recognition";
    
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "On Handle Intent");
        Log.d(TAG, "onReceive(): " + intent);
        Toast.makeText(MyApplication.getmContext(), intent.getAction(), Toast.LENGTH_SHORT).show();
       
    }

Manifest

<application ...

<receiver
            android:name=".Location_system.ActivityRecognitionBroadcastReceiver"
            android:permission="com.google.android.gms.permission.ACTIVITY_RECOGNITION">
            <intent-filter>
                <action android:name="com.example.TRANSITIONS_RECEIVER_ACTION"/>
            </intent-filter>
        </receiver>

</application>


from BroadcastReceiver not receiving any activity recognition broadcast

ExoPlayer+CastPlayer add subtitles (closed captions) using MediaItem

I am trying to configure both SimpleExoPlayer and CastPlayer to display subtitles on device/TV. I create MediaItem as follows:

private fun createMediaItem(url: String, type: PlayerViewSourceType): MediaItem {
        val uri = Uri.parse(url)
        val mediaItemBuilder = MediaItem.Builder()
            .setUri(uri)
        if (type == PlayerViewSourceType.HLS) {
            val subtitle = MediaItem.Subtitle(uri, MimeTypes.TEXT_VTT, "en", C.SELECTION_FLAG_AUTOSELECT)
            mediaItemBuilder.apply {
                setMimeType(MimeTypes.APPLICATION_M3U8)
                setSubtitles(listOf(subtitle))
            }
        } else {
            val subtitle = MediaItem.Subtitle(uri, MimeTypes.TEXT_VTT, "en", C.SELECTION_FLAG_AUTOSELECT)
            mediaItemBuilder.apply {
                setMimeType(MimeTypes.APPLICATION_MP4)
                setSubtitles(listOf(subtitle))
            }
        }

        return mediaItemBuilder.build()
    }

I use same url, because subtitles are coming with video and it works this way on iOS side. Also Subtitles object is the same for both cases so could be created before if-else but I tried different sets of parameters so I left it as it is. It didn't work this way. Unfortunatelly addTextOutput {} is deprecated so I've been searching further and I found out that I can add it as Player.Listener implementation, so I created a class:

private inner class SubtitlesListener() : Player.Listener, TextOutput {
        override fun onCues(cues: MutableList<Cue>) {
            subtitleView.onCues(cues)
        }
    }

And with this class I added another listeners for my players:

playerStorage.simpleExoPlayer.addListener(SubtitlesListener())
playerStorage.castPlayer.addListener(SubtitlesListener())

And to zip it all together I added click listener for CC button:

private fun setupSubtitlesClickListener() {
        ccButton.setOnClickListener {
            when (playerStorage.isDisplayingSubtitles) {
                true -> {
                    playerStorage.showSubtitles(false)
                    ccButton.setImageResource(R.drawable.ic_closed_caption_inactive_24_px)
                    subtitleView.gone()
                }
                else -> {
                    playerStorage.showSubtitles(true)
                    ccButton.setImageResource(R.drawable.ic_closed_caption_white_16_px)
                    subtitleView.visible()
                }
            }
        }
    }

For now only one video in app has subtitles for testing purposes and it is .mp4 video file. Unfortunately this solution doesn't work.
I have found plenty implementations for subtitles, but the latest is from 2020 and it is not applicable here. Also I can't use MergingMediaSource because CastPlayer accepts only MediaItem. SimpleExoPlayer can use it too, so I can create one type of object for both players. Even if I would use MediaSource just for SimpleExoPlayer I still couldn't add subtitles for `CastPlayer.

I can use m3u8 for all cases, so I don't need to read files from separate file.



from ExoPlayer+CastPlayer add subtitles (closed captions) using MediaItem

Dag run not found when unit testing a custom operator in Airflow

I've written a custom operator (DataCleaningOperator), which corrects JSON data based on a provided schema.

The unit tests previously worked when I didn't have to instatiate a TaskInstance and provide the operator with a context. However, I've updated the operator recently to take in a context (so that it can use xcom_push).

Here is an example of one of the tests:

DEFAULT_DATE = datetime.today()

class TestDataCleaningOperator(unittest.TestCase):    
    """
    Class to execute unit tests for the operator 'DataCleaningOperator'.
    """
    def setUp(self) -> None:
        super().setUp()
        self.dag = DAG(
            dag_id="test_dag_data_cleaning",
            schedule_interval=None,
            default_args={
                "owner": "airflow",
                "start_date": DEFAULT_DATE,
                "output_to_xcom": True,
            },
        )
        self._initialise_test_data()

    def _initialize_test_data() -> None:
        # Test data set here as class variables such as self.test_data_correct
        ...

    def test_operator_cleans_dataset_which_matches_schema(self) -> None:
        """
        Test: Attempt to clean a dataset which matches the provided schema.
        Verification: Returns the original dataset, unchanged.
        """
        task = DataCleaningOperator(
            task_id="test_operator_cleans_dataset_which_matches_schema",
            schema_fields=self.test_schema_nest,
            data_file_object=deepcopy(self.test_data_correct),
            dag=self.dag,
        )
        ti = TaskInstance(task=task, execution_date=DEFAULT_DATE)
        result: List[dict] = task.execute(ti.get_template_context())
        self.assertEqual(result, self.test_data_correct)

However, when the tests are run, the following error is raised:

airflow.exceptions.DagRunNotFound: DagRun for 'test_dag_data_cleaning' with date 2022-02-22 12:09:51.538954+00:00 not found

This is related to the line in which a task instance is instantiated in test_operator_cleans_dataset_which_matches_schema.

Why can't Airflow locate the test_dag_data_cleaning DAG? Is there a specific configuration I've missed? Do I need to also create a DAG run instance or add the DAG to the dag bag manually if this test dag is outide of my standard DAG directory? All normal (non-test) dags in my dag dir run correctly.

In case it helps, my current Airflow version is 2.2.3 and the structure of my project is:

airflow
├─ dags
├─ plugins
|  ├─ ...
|  └─ operators
|     ├─ ...
|     └─ data_cleaning_operator.py
|
└─ tests
   ├─ ...
   └─ operators
      └─ test_data_cleaning_operator.py


from Dag run not found when unit testing a custom operator in Airflow

Friday 25 February 2022

Save HTML locally with Javascript

I know that client-side Javascript cannot write data to the local filesystem, for obvious security reasons.

The only way to save data locally with Javascript seems to be with cookies, localStorage, or allow the user to download a file (with a "Save..." dialog box or to the browser's default Download folder).

But is it possible, in the very specific case when the file is accessed locally with an URL like file:///D:/test/index.html (and not through internet) to write data locally ? (without any server language, and even without any server at all: just local browsing of a HTML file)

For example, would it be possible, by clicking on SAVE here:

  <div contenteditable="true" style="height:200px;">Content editable - edit me and save!</div>
  <button>Save</button>

...that such a HTML file (accessed through file:///D:/test/index.html) is overwritten with its new content ? (i.e. the local HTML file should be updated when SAVE is pressed).


enter image description here


TL;DR: Is this possible to SAVE a file thanks to Javascript, when the HTML page is accessed locally?

Note: I want to be able to silently save, not propose a Download/Save dialog box in which the user has to choose where to download, then "Are you sure to want to overwrite" etc.


EDIT : Why this question? I'm doing an in-browser notepad that I can run locally without any server (no Apache, no PHP). I need to be able to save easily without having to deal with Dialog Box "Where do you want to download the file?" and having to always re-browse to the same folder to overwrite the currently-being-edited file. I would like a simple UX like in any notepad program: CTRL+S done, the current file is saved! (example: MS Word doesn't ask to browse where you want to save the file each time you do "Save": CTRL+S, done!)



from Save HTML locally with Javascript

Mobile safari - on screen keyboard hiding some elements

I'm building a very simple POC for an HTML chat app, using flexbox. The idea is to have chat messages which start at the bottom of the message window. Typical stuff.

I did this by using a nested flexbox with an inner div set to flex-direction: column and an outer div set to flex-direction: column-reverse and overflow-y: auto:

<div class="outer">
    <div id="messages" class="inner">
        <div class="message">hello</div>
    </div>
</div>
.outer {
    flex-grow: 1;
    display: flex;
    flex-direction: column-reverse;
    overflow-y: auto;
}

.inner {
    display: flex;
    flex-direction: column;
}

It works well for desktop browsers:

Desktop

It also works fine on iOS safari up to a certain number of messages. However at some point the new messages get hidden behind the onscreen keyboard and the only way to see them is either to manually scroll down or close the on screen keyboard. Note: opening the keyboard again will no longer hide the messages, closing the keyboard seems to reset the scroll.

Opening Safari dev tools reveals something interesting. When selecting an html element Safari thinks it is where it should be, in fact the preceding element is shown:

Mobile

Notice how I selected the last element "Two" but dev tools highlights message "One"

Something else I noticed. Changing the outer div's overflow-y to hidden solves the problem, but obviously I can no longer scroll through the messages.

I'm guessing the issue is related to having two sets of scroll bars, one for the div and one for the page itself which is shifted by the keyboard.

Does anyone know why this is happening and how to prevent it?

I've created a fiddle and also hosted the page on S3

On my phone, adding around 12/13 messages is enough for them to start "hiding" behind the keyboard.



from Mobile safari - on screen keyboard hiding some elements

How to display a scaled up image in an popup window on mouse hover or on click event on an image displayed in a rhandsontable cell in RShiny?

I would like to display a scaled-up popup image on mouseover or on-click event on an image displayed in the rhandsontable cell similar to as shown here in DT table.

enter image description here

I would like to display the popup image for the image displayed in the table created as shown below:

library(rhandsontable)

DF = data.frame(
  comments = c(
    "I would rate it &#x2605;&#x2605;&#x2605;&#x2605;&#x2606;",
    "This is the book about JavaScript"
  ), 
  cover = c(
    "http://ecx.images-amazon.com/images/I/51bRhyVTVGL._SL50_.jpg",
    "http://ecx.images-amazon.com/images/I/51gdVAEfPUL._SL50_.jpg",
 ),
 stringsAsFactors = FALSE
)

rhandsontable(DF, allowedTags = "<em><b><strong><a><big>", 
              width = 800, height = 450, rowHeaders = FALSE) %>%
  hot_cols(colWidths = c(200, 80)) %>%
  hot_col(1, renderer = htmlwidgets::JS("safeHtmlRenderer")) %>%
  hot_col(2, renderer = "
    function(instance, td, row, col, prop, value, cellProperties) {
      var escaped = Handsontable.helper.stringify(value),
        img;
  
      if (escaped.indexOf('http') === 0) {
        img = document.createElement('IMG');
        img.src = value; img.style.width = '80px'; img.style.height = '80px';
  
        Handsontable.dom.addEvent(img, 'mousedown', function (e){
          e.preventDefault(); // prevent selection quirk
        });
  
        Handsontable.dom.empty(td);
        td.appendChild(img);
      }
      else {
        // render as text
        Handsontable.renderers.TextRenderer.apply(this, arguments);
      }
  
      return td;
    }")


from How to display a scaled up image in an popup window on mouse hover or on click event on an image displayed in a rhandsontable cell in RShiny?

Round corners in NestedScrollView with Collapsing Toolbar Layout

I'm making a detail view with a CoordinatorLayout with a header image to which I want to apply rounded edges in the view that has the NestedScrollView, something like this:

introducir la descripción de la imagen aquí

I'm making a detail view with a CoordinatorLayout with a header image to which I want to apply rounded edges in the view that has the NestedScrollView, something like this:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".MainActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="@color/white"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="320dp"
                android:importantForAccessibility="no"
                android:scaleType="centerCrop"
                android:src="@drawable/collapsing_image"
                app:layout_collapseMode="parallax" />

            <com.google.android.material.appbar.MaterialToolbar
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin" />

        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="-20dp"
        android:background="@drawable/rounded_collapsing_toolbar"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="20dp"
            android:text="@string/text_collapsing" />

    </androidx.core.widget.NestedScrollView>

</androidx.coordinatorlayout.widget.CoordinatorLayout>
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#FFFFFF" />
    <corners
        android:topLeftRadius="20dp"
        android:topRightRadius="20dp" />
</shape>

One of the problems is that it starts to do strange things, because when I put the negative margin, when I expand the toolbar I see that -20dp piece of white until it starts to show the image.

I have tried to put as a kind of "fake view" which would go inside the CollapsingToolbar, but the problem that I find here is that being here inside, it also collapses and for example, if I have the toolbar in a different colour than the scroll view, you can see the difference when I expand it...



from Round corners in NestedScrollView with Collapsing Toolbar Layout

browser.cookies.getAll() always returns nothing - Firefox Extension

I have been trying to list all browser cookies in my extension with browser.cookies.getAll(). At first I thought it was a permissions issue, but my permissions appear to be set correctly. Here is my code:

manifest.json

{
    "manifest_version": 2,
    "name": "CookieExample",
    "version": "0.1",

    "applications": {
        "gecko": {
            "id": "cookieexample@example.com"
        }
    },

    "permissions": [
        "cookies",
        "webNavigation",
        "webRequest",
        "webRequestBlocking",
        "<all_urls>"
    ],

    "background": {
        "scripts": ["cookies.js"]
    }        
}

cookies.js

browser.cookies.getAll({}, function(cookies) {
    console.log(cookies);
});

The console simply logs [] as the return value. I don't know where I've gone wrong or if it's a problem with the browser. Cookie Manager works just fine and lists all browser cookies without a hitch. Looking into its source code, the only difference is that it uses a cookie store ID to query for cookies, whereas I used nothing.



from browser.cookies.getAll() always returns nothing - Firefox Extension

'_lifecycleState != _ElementLifecycle.defunct': is not true. Error in Flutter

I've encountered an error which says

'_lifecycleState != _ElementLifecycle.defunct': is not true.

enter image description here

I came across this issue when I tried to change the state in dispose() method.

      @override
      void dispose() {
        setState(() => _successErrorLoader = "");
        setState(() => _ackMessage = "");
      }

I want to do some state changes when an component is unmounted (removed from the screen). Please provide any alternative solution or a fix for this error.



from '_lifecycleState != _ElementLifecycle.defunct': is not true. Error in Flutter

Thursday 24 February 2022

Getting permutation index and permutation at index faster than the provided solution

Thanks to this answer, here is how I'm getting permutation index and permutation at an index:

def get_Cl(distinct):
Cl = []
for i in range(1, distinct+1):  # i is distincct
    c = [0] * i + [1, 0]
    C = [c]
    for l in range(2, distinct+1):
        c = [
                c[d] * d + c[d + 1] * (distinct - d)
                for d in range(i + 1)
            ] + [0]
        C.append(c)
    Cl.append(C)
return Cl


def item_index(item, distinct, n_symbols, Cl):
    length = len(item)
    offset = 0
    seen = set()
    for i, di in enumerate(item):
        for d in range(n_symbols):
            if d == di:
                break
            if d in seen:
                # test = Cl[distinct][length - 1 - i][len(seen)]
                offset += Cl[distinct][length - 1 - i][len(seen)]
            else:
                offset += Cl[distinct][length - 1 - i][len(seen) + 1]
        seen.add(di)
    return offset


def item_at(idx, length, distinct, n_symbols, Cl):
    seen = [0] * n_symbols
    prefix = [0] * length
    used = 0
    for i in range(length):
        for d in range(n_symbols):
            if seen[d] != 0:
                branch_count = Cl[distinct][length - 1 - i][used]
            else:
                branch_count = Cl[distinct][length - 1 - i][used + 1]
            if branch_count <= idx:
                idx -= branch_count
            else:
                prefix[i] = d
                if seen[d] == 0:
                    used += 1
                seen[d] = 1
                break
    return prefix


if __name__ == "__main__":
    Cl = get_Cl(300)
    item = item_at(idx=432,length=300,distinct=200, n_symbols=300, Cl=Cl)
    print(item)
    print(item_index(item=item, distinct=200, n_symbols=300, Cl=Cl))

It works fine unless numbers get bigger then it gets very slow. Wondered if it is possible to improve this code like this answer?

The reason I get Cl in a separate line is that for a fixed distinct there will be thousands of calls on item_at and item_index, so the Cl is the same if distinct is the same thus no need for call it for each item_at or item_index.



from Getting permutation index and permutation at index faster than the provided solution

PyAutoGUI - result will only get parsed once

I'm trying to automate a simple thing. A popup pops up, my script finds it and clicks on the button I took a screenshot of (erteilen.png). Half a second later the same popup pops up again, but my script won't notice it.

This is my code:

import pyautogui as pg

while True:
    window = pg.locateOnScreen("erteilen.png", minSearchTime=3, confidence=0.9)
    try:
        print(window)
        pg.click(x=window.left+int(window.width/2), y=window.top+int(window.height/2), clicks=3)
    except Exception as e:
        print("Error:", e)
        break

It will click on the found window, then the same window opens again, but the script won't locate it again. When I click in the command window, it seems like pyautogui refreshes it's screen and then finds the window.

How can I tell PyAutoGUI to 'refresh' what it sees itself, so that it gets updated informations and finds the new windows as well?

Thanks in advance!

Michael



from PyAutoGUI - result will only get parsed once

How to release GIL after Py_Initialize?

I am trying to embed python in a GUI application, and so I have a the python interpreter initialized in the main thread of the application, and I may launch python scripts from another one.

I read about PyGILState_Ensure and PyGILState_Release, and I put them around my code which launch python script in my subthread. But the call is blocking, and my code is never run.

It seems that my main thread is not releasing the GIL (checked with PyGILState). The GIL initialization is now done in Py_Initialize, and lot of old doc talk about PyEval_InitThreads and other now deprecated functions.

So with a modern python, how do we release a thread from the GIL after Py_Initialize ?



from How to release GIL after Py_Initialize?

JavaScript keydown in Chrome not capturing a single keypress that outputs multiple Unicode characters

I am working with Yiddish, for which some letters consist of two Unicode characters. For example, אַ consists of U+05D0 + U+05B7. There are single code variants of these characters (eg. U+FB2E for אַ), but most keyboards take the former approach.

I'd like to capture input from a Yiddish keyboard using keydown, but I'm having trouble with these keys that output multiple Unicode characters. In particular, I'm using a simple code:

$(document).keydown(function (event) {
    if (!event.metaKey) {
        console.log(event.key);
    }
});

See it on JSFiddle.

I'm on Windows, and on Firefox, I'm getting the expected result when I press אַ (which is the letter A on my keyboard, and outputs U+05D0 U+05B7): namely, the console logs אַ. However, on Chrome (version 98), I get "Unidentified" as the output (although I get the expected result for any key that outputs a single Unicode character). The same thing happens on Edge. I don't have a Mac, but a friend tested for me and weirder things happened: it logged the U+05B7 but not the U+05D0. Safari worked fine for him, though.

Any idea what's going on, and how to fix it?



from JavaScript keydown in Chrome not capturing a single keypress that outputs multiple Unicode characters

Custom linkhandler does not show up in PageLinkChooser

I am following the Wagtail docs to create a custom link handler:

myapp.handlers.py

from django.contrib.auth import get_user_model
from wagtail.core.rich_text import LinkHandler

class UserLinkHandler(LinkHandler):
    identifier = 'user'

    @staticmethod
    def get_model():
        return get_user_model()

    @classmethod
    def get_instance(cls, attrs):
        model = cls.get_model()
        return model.objects.get(username=attrs['username'])

    @classmethod
    def expand_db_attributes(cls, attrs):
        user = cls.get_instance(attrs)
        return '<a href="mailto:%s">' % user.email

my_app/wagtail_hooks.py

from wagtail.core import hooks
from my_app.handlers import MyCustomLinkHandler

@hooks.register('register_rich_text_features')
def register_link_handler(features):
    features.register_link_type(LinkHandler)

However, the handler does not show up in the admin widget. The expected behaviour is it should be in an option in the link type bar:

enter image description here

I've followed the docs exactly, is there something missing?



from Custom linkhandler does not show up in PageLinkChooser

Webkit - Cannot Scroll Up Without First Scrolling Down

I ran into this odd bug on Webkit browsers where if a user attempts to scroll up in my div, they are unable to do so, without first scrolling down - if the user is at the bottom of the div they are not able to scroll up at all. More details and a video can be found on this issue: https://github.com/manufont/react-swipeable-bottom-sheet/issues/21?_pjax=%23js-repo-pjax-container

I'm not sure what the exact cause of this issue is, but I'm trying to implement a solution where I intercept the scroll event, and if the user is attempting to scroll up - I first scroll down one pixel and then allow the user to scroll up. I added the onScroll handler to my component and have the following code:

const handleScroll = e => {
    const element = e.target;
    element.scrollTo(0, element.scrollTop + 1);
    if (element.scrollHeight - element.scrollTop === element.clientHeight) {
        // do something at end of scroll
        console.log('END OF SCROLL');
        element.scrollTo(0, element.scrollTop - 1);
    }
};

In this code I'm always scrolling down one pixel, but the problem is I'm unable to detect the direction of scroll - I looked at various solutions which do this, including this one: https://stackoverflow.com/a/62497293/4909000 and https://stackoverflow.com/a/50412319/4909000 but neither of them worked for me - currentTarget.scrollY was undefined and the hook solution randomly printed scrolling down and didn't seem to work at all.



from Webkit - Cannot Scroll Up Without First Scrolling Down

Node canvas use fallback font for unknown characters

I'm using Node-Canvas to print text on an image and trying to figure out how to ensure strange characters are displayed correctly, even if the main font can't display them.

From what I found online you have to use registerFont with a font that can display those characters to fall back on, but it seems like it doesn't use it automatically, and I couldn't find anything on how to tell it do use a fallback font.

When registering a font that can display the character (Code2000) it still appears like this (the "ᗩ" character isn't displayed correctly):

(Trying to print HELLO WORLD, I'M ᗩcł!)
This is my code:

//load some fallback fonts for custom characters (arial & code2000 in this case)
canvas.registerFont('./Assets/Fonts/arial.ttf', {family: 'Arial'})
canvas.registerFont('./Assets/Fonts/code2000.ttf', {family: 'Code2000'})
//load the Uni Sans Heavy custom font
canvas.registerFont('./Assets/Fonts/Uni_Sans_Heavy.ttf', {family: 'Uni Sans'})
let cnvs = canvas.createCanvas(740, 260)
let ctx = cnvs.getContext('2d')
ctx.fillStyle = "#fff"
ctx.font = '50px Uni Sans'
ctx.fillText(`HELLO WORLD, I'M ᗩcł!`, 50, 100);
    
message.channel.send({files: [{ attachment: cnvs.toBuffer() }]}).catch(allerrors)

The "Code2000" font can display the character correctly for sure, so I thought it'd automatically fall back to that, but it doesn't. Is there a way to use the fallback font automatically? If not, how do I tell it which characters to use it on?



from Node canvas use fallback font for unknown characters

Python openAL 3D sound

I just started with python and I am making program for audio manipulation. I am trying to implement 3D sound with openAL in my python application, but I just can get it to work

this is my code for 3D sound:

from openal.loaders import load_wav_file
from openal.audio import *

sink = SoundSink()   
listener = SoundListener()
SoundSink.activate(sink)
listener.position = (0, 0, 0)
listener.velocity = (0, 0, 0)
listener.orientation = (0, 0, -1, 0, 1, 0)
source = SoundSource()
wavsound = load_wav_file("test.wav")
source.queue(wavsound)
#SoundSink.play(source)
sink.play(source)

The code executes, but it doesn't play the sound



from Python openAL 3D sound

Wednesday 23 February 2022

Tone.js audio filters not being heard

I'm trying to add filter effects to an audio stream I have playing on my website. I'm able to connect the Tone.js library to the audio stream but I'm not hearing any changes in the audio stream playing on the website. I'm not seeing any errors in the console and I've tried adjusting the filter from 50 to 5000 but nothing seems to have any effect on the audio. Do I need to set up the new Tone.Player() to actually hear the audio? If so, how do you go about setting up the Player if there is no src for the existing audio element.

    $('#testBtn').click(async function () {
        const audioElement = document.getElementById('theAudioStream');
        const mediaElementSource = Tone.context.createMediaElementSource(audioElement);
        const filter = new Tone.Filter(50, 'lowpass').toDestination();
        Tone.connect(mediaElementSource, filter);
        await Tone.start();
        console.log("Started?");
    });

The audio stream I'm trying to modify is set up from a JsSip call. The code to start the stream is as follows:


    var audioStream = document.getElementById('theAudioStream')

    //further down in code    

    currentSession.answer(options);
    if (currentSession.connection) {
        currentSession.connection.ontrack = function (e) {
          audioStream.srcObject = e.streams[0];
          audioStream.play();
        }
    }

I click the test button after the call has started so I know the audio stream is present before initializing the Tone.js Filters



from Tone.js audio filters not being heard

Naives Bayes Classifier for bag of vectorized sentences

Summary : How to train a Naive Bayes Classifier on a bag of vectorized sentences ?

Example here :

X_train[0] = [[0, 1, 0, 0], [1, 0, 0, 1], [0, 0, 0, 1]]
y_train[0] = 1

X_train[1] = [[0, 0, 0, 0], [0, 1, 0, 1], [1, 0, 0, 1], [0, 1, 0, 1]]
y_train[1] = 0

.


1) Context of the project : perform sentiment analysis on batch of tweets to perform market prediction

I am working on a sentiment analysis for stock market classification. As I am new to these techniques, I tried to replicate one from this article : http://cs229.stanford.edu/proj2015/029_report.pdf

But I am facing a big issue with it. Let me explain the main steps of the article I realized :

  1. I collected a huge amount of tweets during 4 months (7 million)
  2. I cleaned then (removing stop words, hashtags, mentions, punctuation, etc...)
  3. I grouped them into period interval of 1 hour
  4. I created a target that tell if the price of the Bitcoin has gone down or up after one hour (0 = down ; 1 = up)

What I need to do next is to train my Bernoulli Naive Bayes Model with this. To do this, the article mentions to vectorize the tweets this way.

enter image description here

[.....] enter image description here

What I did with the CountVectorizer class from sklearn.

2 ) The issue : the dimension of the inputs doesn't match Naive Bayes standards

But then I encounter an issue when I try to fit the Bernoulli Naive Bayes model, following the article method :

enter image description here

So, one observation is shaped this way :

  • input shape (one observation): (nb_tweets_on_this_1hour_interval, vocabulary_size= 10 000)
    one_observation_input = [
        [0, 1, 0 ....., 0, 0], #Tweet 1 vectorized
        ....,
        [1, 0, ....., 1, 0]    #Tweet N vectorized
    ]#All of the values are 0 or 1
  • output shape (one observation): (1,)

    one_observation_output = [0] #Can only be 0 or 1

When I tried to fit my Sklearn Bernoulli Naive Bayes model with this type of value, I am getting this error

>>> ValueError: Found array with dim 3. Estimator expected <= 2.

Indeed, the model expects binary input shaped this way :

  • input : (nb_features)

    ex: [0, 0, 1, 0, ...., 1, 0, 1]

while I am giving it vectors of binary values !

3 ) What I have tried

So far, I tried several things to resolve this :

  • Associating the label for every tweet, but the results are not good since the tweets are really noisy
  • Flatten the inputs so the shape for one input is (nb_tweets_on_this_1hour_interval*vocabulary_size, ). But the model can not train as the number of tweets every hour is not constant.

4 ) Conclusion

I don't know if the error comes from my misunderstanding of the article or of the Nayes Bayes models.

How to train efficiently a naive bayes classifier on a bag of tweets ?

Here is my training code :


    bnb = BernoulliNB()

    uniqueY = [0, 1]#I give the algorithm the 2 classes I want to classify the tweets with. This is needed for the partial fit

    for _index, row in train_df.iterrows():#I have to use a for loop to partialy fit my Bernouilli Naive Bayes classifier to prevent from out of memory issues

        #row["Tweet"] contains all the (cleaned) tweets over 1hour interval this way  : ["I like Bitcoin", "Nice portfolio", ...., "I am the last tweet of the interval"]
        X_train = vectorizer.transform(row["Tweet"]).toarray()
        #X_train contrains all of the row["Tweet"] tweets vectorizes with a bag of words algorithm which return this kind of data : [[0, 1, 0 ....., 0, 0], ....,[1, 0, ....., 1, 0]]

        y_train = row["target"]
        #Target is 0 if the market is going down after the tweets and 1 if it is going up

        bnb.partial_fit([X_train], [y_train], uniqueY)
        #Again, I use partial fit to avoid out of memory issues



from Naives Bayes Classifier for bag of vectorized sentences

When recognizing hand gesture classes, I always get the same class in Keras

When recognizing hand gesture classes, I always get the same class, although I tried changing the parameters and even passed the data without normalization:

df_train = pd.read_csv('train_dataset.csv')
df_train = df_train.drop(columns=['Unnamed: 0'], axis=1)
df_train = df_train.fillna(0)

x_train = df_train.drop(['y'], axis=1)
y_train = df_train['y']

x_train = x_train / 310

model = keras.models.Sequential([Dense(32, input_shape=(42,), activation='relu'),
                                Dense(64, activation='relu'),
                                Dense(6, activation='softmax')])

model.compile(optimizer='adam',
             loss='categorical_crossentropy',
             metrics=['accuracy'])

model.fit(x_train, y_train_cat, batch_size=16, epochs=9, validation_split=0.2)

model.save("gestures_model.h5")

Here is a main code:

REV_CLASS_MAP = {
    0: "up",
    1: "down",
    2: "right",
    3: "left",
    4: "forward",
    5: "back"
}

def mapper(val):
    return REV_CLASS_MAP[val]

if len(data[data.index(new_row)]) > 0:
    df = pd.DataFrame(data, columns=columns)
    df = df.fillna(0)
    df = df / 310
    pred = model.predict(df)
    move_code = np.argmax(pred[0])
    user_move_name = mapper(move_code)
    print(user_move_name)

Here is an example of input data:

56,172,72,169,88,155,100,144,111,139,78,120,81,94,82,77,82,62,66,120,62,104,62,124,64,136,54,122,50,110,52,130,55,139,43,126,40,114,42,129,45,137,0

What am I doing wrong and how to fix it? I noticed that in my data there are rows in which there is only one number. Could this be the cause of my problem? ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ P.S I am new to neural networks and keras.

New

Here is df_train before processing:

,x11,x21,x12,x22,x13,x23,x14,x24,x15,x25,x16,x26,x17,x27,x18,x28,x19,x29,x110,x210,x111,x211,x112,x212,x113,x213,114,214,115,x215,x116,x216,x117,x217,x118,x218,x119,x219,x120,x220,x121,x221,y
56,172,72,169,88,155,100,144,111,139,78,120,81,94,82,77,82,62,66,120,62,104,62,124,64,136,54,122,50,110,52,130,55,139,43,126,40,114,42,129,45,137,0
...
84,166,96,158,108,143,108,131,101,127,87,145,87,128,90,118,94,111,74,147,76,119,81,114,84,115,64,148,66,120,72,119,74,124,56,148,57,124,61,124,63,129,5

Here is df_train after processing:

     x11  x21  x12  x22  x13  x23  x14  ...  x119  x219  x120  x220  x121  x221    y
0     56  175   73  168   88  155  101  ...    42   113    44   130    47   138  0.0
1    172   72  169   88  155  100  144  ...   114    42   129    45   137     0  0.0
2    172   72  169   88  155  100  144  ...   114    42   129    45   137     0  0.0
3    174   74  167   89  155  101  144  ...   115    44   130    46   137     0  0.0
4    174   74  169   90  155  101  144  ...   114    44   128    46   136     0  0.0
..   ...  ...  ...  ...  ...  ...  ...  ...   ...   ...   ...   ...   ...   ...  ...
843  166   96  158  108  143  108  131  ...   124    61   124    63   129     5  0.0
844  166   94  158  105  145  104  132  ...   128    58   130    59   134     5  0.0
845  164   90  155  101  141  100  129  ...   126    55   129    57   134     5  0.0
846  158   88  152   99  140   96  128  ...   142    54   150    58   146     5  0.0
847  158   88  152   99  140   96  128  ...   142    54   150    58   146     5  0.0

⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀



from When recognizing hand gesture classes, I always get the same class in Keras

Cannot add google ads event to woocoommerce_add_to_cart hook

While it should be a few minutes job, it took me more than 10 hours trying to figure out why the following snippet is working but not as expected, although the site doesn't use ajax for add_to_cart events.

For a very wierd reason the page refreshes when the code is active. I realize this because the log in the console(added_to_cart) disappears after a few moments of loading. The wierd thing is that it has nothing to do with the hook that i'm using(although i also tried woocommerce_add_to_cart_validation with the exact same results) because if i leave only the console.log message it doesn't have the same behavior. It's like the gtag script is forcing a page reload.

Normally this shouldn't be an issue because the event is actually sent to google ads, however there are other scripts that should run afterwards which do not(such as google analytics and others).

add_action( 'woocommerce_add_to_cart', 'custom_add_to_cart', 10, 2 );
function custom_add_to_cart( $cart_item_key, $product_id ) {
    $_product = wc_get_product($product_id);
    $price = $_product->get_price();
    
    $current_url = home_url( $_SERVER['REQUEST_URI'] );
    ?>
        console.log('added_to_cart');
        <script async src="https://www.googletagmanager.com/gtag/js?id=<?php echo ADS_ID ?>"></script>
        <script>
            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}
                gtag('js', new Date());

                gtag('config', '<?php echo ADS_ID ?>');
        </script>
    <script type="text/javascript">
        function gtag_report_conversion(url) {
            var callback = function () {
                if (typeof(url) != 'undefined') {
                    window.location = url;
                }
            };
            gtag('event', 'conversion', {
                'send_to': '<? echo ADS_ADD_TO_CART; ?>',
                'value': <?php echo $price  ?>,
                'currency': 'EUR',
                'event_callback': callback
            });
            return false;
        }
        gtag_report_conversion('<?php echo $current_url; ?>');
    </script>
    <?php
}

any ideas?



from Cannot add google ads event to woocoommerce_add_to_cart hook

Segmentation of 3D mesh and feature extraction

I have five pictures of wound models taken from different angles links for the pictures is provided here

I have used SFM for computing a mesh , the picture of the mesh is presented below enter image description here. I would like to extract only the features associated with the wound region compute volume and depth accordingly.

In order to solve this question, i have used U-Net segmentation to generate a 2D mask of the wound from 2d pictures , an example of 2D mask generated using U-Net is shown below .

I would like to know how i can map this mask onto 3D mesh and extract specific region within the 3D mesh which deals with wound part while removing other regions.

Any other ideas on how to segment the 3D mesh and extract specific region of interest are greatly appreciated, since i don't have different wound models i cannot apply supervised learning using 3D U-Net.



from Segmentation of 3D mesh and feature extraction

Python Firebase (Real-time database) on Replit

I want to connect to firebase on replit using python. I'm using the code below:

from firebase import firebase

firebase = firebase.FirebaseApplication("my firebase url", None)

data = {
  'ddfjaklfbja': 'dklabja;kdlf',
  'adfjlkgadjf': 'dkaljbaowq',
  'afbiouadofpia': 'dsajklbjanzm'
}

result = firebase.post('/test1', data)
print(result)

However, when I try to run it, it returns an error saying that there is no module named urllib3:

ModuleNotFoundError: No module named 'urllib3'

When I try to use the packages tab to install it on the left, it does not install and returns with the same error (there are multiple lines but the last line says this). How can I fix it?

enter image description here enter image description here



from Python Firebase (Real-time database) on Replit

can anyone help understanding kotlin code below

Since I don't know kotlin, so please anyone who know kotlin and Java please convert the below code to java it would really help me.

here is the code:

private var checkedRadioButton: CompoundButton? = null

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.itemView.radio_button.setOnCheckedChangeListener
 (checkedChangeListener)

if (holder.itemView.radio_button.isChecked) checkedRadioButton = 
 holder.itemView.radio_button
 }

 private val checkedChangeListener = 
 CompoundButton.OnCheckedChangeListener { compoundButton, isChecked 
 ->
checkedRadioButton?.apply { setChecked(!isChecked) }
checkedRadioButton = compoundButton.apply { setChecked(isChecked) }
}

please help!



from can anyone help understanding kotlin code below

Tuesday 22 February 2022

Angular: Testing apis from component

I have started learning how to test angular projects. So far basic unit testing is working fine for me but for the dependency testing especially when API services are injected into the component I am facing issue for providing HttpClient. I have tried different solutions but none is working for me.

Service

// Present in HttpClientService file
getDisposition() {
  return this.http.get<{ message: string, data: { dispositionList: Disposition[] } }>(`${this.URL}/disposition/get`);
}

// Present in FileProcessService file
deleteMedia(media: string) {
    return this.http.delete<{ message: string }>(`${this.URL}/certificate/delete?certificate=${media}`);
}

add-edit-activity.component.ts

import { HttpEventType } from '@angular/common/http';
import { Component, ElementRef, Inject, OnInit, ViewChild } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
import { AssignedPerson } from '@model/assigned-person.model';
import { Disposition } from '@model/disposition.model';
import { mimeTypes } from '@model/mime-type';
import { FileProcessService } from '@service/file-process.service';
import { HttpClientService } from '@service/http-client.service';
import { DeleteComponent } from '@shared/delete/delete.component';
import { CustomErrorStateMatcher } from '@validator/error-state-matcher';
import { ToastrService } from 'ngx-toastr';

@Component({
  selector: 'app-add-edit-activity',
  templateUrl: './add-edit-activity.component.html',
  styleUrls: ['./add-edit-activity.component.css']
})
export class AddEditActivityComponent implements OnInit {

  constructor(private fb: FormBuilder, private sanitizer: DomSanitizer, private dialogRef: MatDialogRef<AddEditActivityComponent>, @Inject(MAT_DIALOG_DATA) public data: any,
    private _http: HttpClientService, private _fileService: FileProcessService, private toastr: ToastrService, private dialog: MatDialog,) { }

  re = new RegExp(/^[a-zA-Z-]*/, 'g');
  ISOstamp = { T: ' ', Z: '000' };
  matcher = new CustomErrorStateMatcher();
  dispositionList: Disposition[] = [];
  assignedPersonList: AssignedPerson[] = [];
  filterAssignedPersonList: AssignedPerson[] = [];
  uploaded = false;
  uploadProgress = false;
  fileURL: SafeUrl;
  activityForm = this.fb.group({
    gaugeId: [this.data.gaugeId, Validators.maxLength(9)], createTimeStamp: [{ value: new Date().toISOString().replace(/[TZ]/g, m => this.ISOstamp[m]), disabled: true }],
    user: [{ value: sessionStorage.getItem('username'), disabled: true }], disposition: ['', [Validators.required, Validators.maxLength(30)]],
    assignedPersonName: ['', Validators.maxLength(30)], department: ['', Validators.maxLength(20)],
    shift: ['', Validators.maxLength(1)], remark: ['', Validators.maxLength(50)],
    calibrationDate: ['', Validators.maxLength(10)], attachment: ['', Validators.maxLength(255)]
  });

  @ViewChild('file') certificate: ElementRef;

  ngOnInit(): void {
    this.data.type.match(this.re)[0] === 'Update' && this.setFormValues();
    this._http.getDisposition().subscribe(response => this.dispositionList = response.data.dispositionList);
    this._http.getAssignedPerson().subscribe(response => this.assignedPersonList = this.filterAssignedPersonList = response.data.assignedToList);
  }

  get GaugeId() {
    return this.activityForm.get('gaugeId');
  }

  get TimeStamp() {
    return this.activityForm.get('createTimeStamp');
  }

  get Attachment() {
    return this.activityForm.get('attachment');
  }

  get Disposition() {
    return this.activityForm.get('disposition');
  }

  get DispositionValue() {
    return this.dispositionList.map(e => e.dispositionType).indexOf(this.Disposition.value) < 0;
  }

  get AssignedTo() {
    return this.activityForm.get('assignedPersonName');
  }

  get AssignedToValue() {
    return this.assignedPersonList.map(e => `${e.firstName} ${e.lastName}`).indexOf(this.Disposition.value) < 0;
  }

  private async setFormValues() {
    this.activityForm.patchValue({ ...this.data });
    if (this.data.attachment) {
      this.uploadProgress = true;
      this.uploaded = true;
      await this.fetchUploadedFile(this.data.attachment, mimeTypes[this.data.attachment.split('.')[1]]);
      this.activityForm.markAsPristine();
    }
  }

  searchAssignedPerson(event) {
    if (event.target.value) {
      this.filterAssignedPersonList = [];
      for (let person of this.assignedPersonList) {
        if (person.firstName.toLowerCase().startsWith(event.target.value.toLowerCase())) {
          this.filterAssignedPersonList.push(person);
        }
      }
    } else { this.filterAssignedPersonList = this.assignedPersonList }
  }

  upload(event) {
    const file: File = event.target.files[0];
    this.certificate.nativeElement.value = '';
    if (file.size > (20 * 1000 * 1000)) { // Checking if File size is above 20MB
      this.toastr.error('Size of ' + file.name + ' is above 20MB');
      return;
    }
    const fd = new FormData();
    fd.append('certificate', file, file.name);
    this.processAttachment(fd);
  }

  private processAttachment(file: FormData) {
    this._fileService.uploadMedia(file).subscribe(event => {
      if (event.type === HttpEventType.UploadProgress) { this.uploadProgress = true }
      if (event.type === HttpEventType.Response) {
        let media = event.body.data.Certificate;
        this.fetchUploadedFile(media.fileName, media.fileType);
        this.toastr.info(event.body.message);
      }
    }, error => {
      this.toastr.error(error.error.message);
      this.uploadProgress = false;
    });
  }

  private async fetchUploadedFile(file: string, mimeType: string) {
    try {
      let response = await this._fileService.getMedia(file).toPromise();
      this.fileURL = this.sanitizer.bypassSecurityTrustUrl(URL.createObjectURL(new Blob([response], { type: mimeType })));
      this.uploaded = true;
      this.uploadProgress = false;
      this.activityForm.patchValue({ attachment: file });
      this.Attachment.markAsDirty();
    } catch (error) {
      this.uploadProgress = false;
      this._fileService.processError(error.error)
    }
  }

  deleteFile() {
    this.dialog.open(DeleteComponent, {
      width: '350px', disableClose: true
    }).afterClosed().subscribe(response => {
      if (response) {
        this._fileService.deleteMedia(this.Attachment.value).subscribe(response => {
          this.toastr.info(response.message);
          this.activityForm.patchValue({ attachment: '' });
          this.Attachment.markAsDirty();
          this.uploaded = false;
        }, error => this.toastr.error(error.error.message));
      }
    });
  }

  async doAction() {
    let message = '';
    if (this.data.type.match(this.re)[0] === 'Add') {
      message = await (await this._http.addActivityLog(this.activityForm.getRawValue()).toPromise()).message;
    } else {
      message = await (await this._http.updateActivityLog(this.GaugeId.value, this.TimeStamp.value, this.activityForm.getRawValue()).toPromise()).message;
    }
    this.dialogRef.close(message);
  }
}

add-edit-activity.component.spec.ts

import { ComponentFixture, TestBed, tick } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { FileProcessService } from '@service/file-process.service';
import { HttpClientService } from '@service/http-client.service';
import { of } from 'rxjs';
import { delay } from 'rxjs/operators';
import { AddEditActivityComponent } from './add-edit-activity.component';

describe('AddEditActivityComponent', () => {
  let component: AddEditActivityComponent;
  let fixture: ComponentFixture<AddEditActivityComponent>;
  let _http: HttpClientService, _file: FileProcessService;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [AddEditActivityComponent],
      imports: [FormsModule, ReactiveFormsModule],
      providers: [
        { provide: MatDialogRef, useValue: {} },
        { provide: MAT_DIALOG_DATA, useValue: { type: 'Add Activity Log', gaugeId: 'W-001' } },,
        { provider: HttpClientService, useValue: null },
        { provider: FileProcessService, useValue: null }
      ]
    }).compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(AddEditActivityComponent);
    component = fixture.debugElement.componentInstance;
    _http = fixture.debugElement.injector.get(HttpClientService);
    _file = fixture.debugElement.injector.get(FileProcessService);
    fixture.detectChanges();
  });
  
  // These 2 tests throwing error.
  it('SHOULD mock http service', () => {
    let spy = spyOn(_http, 'getDisposition').and.callFake(() => {
      return of({
        message: '',
        data: { dispositionList: [] }
      }).pipe(delay(100));
    });
    component.ngOnInit();
    tick(100);
    expect(component.dispositionList).toEqual([]);
  });

  it('SHOULD mock file service', () => {
    let spy = spyOn(_file, 'deleteMedia').and.callFake((file: string) => {
      return of({ message: '' }).pipe(delay(100));
    });
    component.deleteFile();
    tick(100);
    expect(component.uploaded).toBe(false);
  });
});

The error that am getting for those 2 tests (I'm providing the error of 1 test case, the same is coming for the 2nd one also):

  1. SHOULD mock http service AddEditActivityComponent Error: Invalid provider for the NgModule 'DynamicTestModule' - only instances of Provider and Type are allowed, got: [..., ..., ..., ..., ?undefined?, ..., ...] at throwInvalidProviderError (node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:240:1) at providerToFactory (node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:11550:1) at providerToRecord (node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:11521:1) at R3Injector.processProvider (node_modules/@angular/core/ivy_ngcc/fesm2015/core.js:11424:1) Error: : could not find an object to spy upon for getDisposition() Usage: spyOn(, ) Error: : could not find an object to spy upon for getDisposition() Usage: spyOn(, ) at

Anyone, please help what's the exact error happening with my test cases? Stuck here for almost 2 days.



from Angular: Testing apis from component

How to get the Z,Y,X Rotation of Android/iOS Device in React Native? (Pitch,Yaw,Roll)?

I tried using: "react-native-sensors" library

https://github.com/react-native-sensors/react-native-sensors/blob/master/docs/API.md#orientation-observableqx-number-qy-number-qz-number-qw-number-pitch-number-roll-number-yaw-number-timestamp-string

import { orientation } from "react-native-sensors";

const subscription = orientation.subscribe(({ qx, qy, qz, qw, pitch, roll, yaw, timestamp }) =>
    console.log({ qx, qy, qz, qw, pitch, roll, yaw, timestamp })
);

I tried using their given pitch,roll,yaw and converted from radian_to_degress still not the same values as the emulator.

They also provide a quaternion to Angles function

function quaternionToAngles(q) {
    let data = q;

    let ysqr = data.y * data.y;
    let t0 = -2.0 * (ysqr + data.z * data.z) + 1.0;
    let t1 = +2.0 * (data.x * data.y + data.w * data.z);
    let t2 = -2.0 * (data.x * data.z - data.w * data.y);
    let t3 = +2.0 * (data.y * data.z + data.w * data.x);
    let t4 = -2.0 * (data.x * data.x + ysqr) + 1.0;

    t2 = t2 > 1.0 ? 1.0 : t2;
    t2 = t2 < -1.0 ? -1.0 : t2;

    const toDeg = 180 / Math.PI;

    const euler = {};
    euler.pitch = Math.asin(t2) * toDeg;
    euler.roll = Math.atan2(t3, t4) * toDeg;
    euler.yaw = Math.atan2(t1, t0) * toDeg;

    return euler;
}

The function gives wrong results for roll,yaw and pitch. I dont want to dive into the Math of this. google searching gives 100x different equations.

enter image description here

Im searching for simple equations to get the Z,Y,X Rotations of my Device just like the Android Emulator provides. If Z-Rot Value is "90"(on emulator) my program should also receive the same value. I have access to gyrometer,barometer,accelometer etc.

PS: I wasted way to much time on google for a problem that should be solvable with a copy paste after one google search so I hope this question will help.



from How to get the Z,Y,X Rotation of Android/iOS Device in React Native? (Pitch,Yaw,Roll)?

BottomNavigationView icons not highlighted with SDK 31

I updated to compileSdkVersion 31 and now when tapping on a BottomNavigationView item it does not always highlight the icon or show the fragment the BottomNavigationView item id points to.

There are 3 bottom navigation tabs called Home, Actions, My Progress. From the Home fragment, you can navigate to SubFragment.

So the flow might be to start at Home --> go to SubFragment --> go to Actions with the BottomNavigationView --> and then tap on Home to go back. What this did before the update was open the Home fragment (desired behavior). Now when tapping on the Home icon it shows SubFragment and does not highlight the icon.

enter image description here

More details

This is the navController setup:

bottomNavigationView = findViewById(R.id.bottom_navigation_view)

val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController = navHostFragment.navController
bottomNavigationView.setupWithNavController(navController)

The nav_graph structure is like this:

    <fragment
            android:id="@+id/home"
            android:name="com.example.app.home"
            android:label="Home"
            tools:layout="@layout/home" 

            <action
                android:id="@+id/action_home_fragment_to_sub_fragment"
                app:destination="@id/sub_fragment"/>
    </fragment>

    <fragment
            android:id="@+id/subfragment"
            android:name="com.example.app.subfragment"
            android:label="Sub Fragment"
            tools:layout="@layout/subfragment" />

    <fragment
            android:id="@+id/actions"
            android:name="com.example.app.actions"
            android:label="Actions"
            tools:layout="@layout/actions" />

    <fragment
            android:id="@+id/myprogress"
            android:name="com.example.app.myprogress"
            android:label="My Progress"
            tools:layout="@layout/myprogress" />

The menu items id's for the BottomNavigationView are identical to nav_graph.

I thought the issue might be with the nav_graph structure not playing well with the new SDK, so I tried adjusting the structure of the nav_graph so that each navigation tab was within its own like this question answer has setup. It highlights the tab with this approach but still does not navigate to Home like the example above. Only to SubFragment.

Ideas on what I might be missing are appreciated!



from BottomNavigationView icons not highlighted with SDK 31

Send audio file via Andoid phone call without internet

I have 2 Android phone (I can be rooted on them) . I can write on each of them Application. But I have no internet for those phone.

I want to send audio file from 1 phone to another via phone call and that audio file will be binary same.

I know that in phone there is audio encoder that may change the data (encoding/pack/compress data) can I skip on this module so I can send audio file via phone call that will be exactly same binary?



from Send audio file via Andoid phone call without internet

Accessing YouTube Data API without user intervention

I'm coding a music website that allows the user to create YouTube lists.

My first try has been with JS:

https://developers.google.com/youtube/v3/code_samples/javascript

The process implies an initial authorization, as you can see in this piece of HTML:

<div id="login-container" class="pre-auth">
    This application requires access to your YouTube account. Please <a href="#" id="login-link">authorize</a> to continue.
</div>

Once you click on the link, a modal like this displays itself:

Modal

So you have to choose an account of your own -that moreover must be included in my GCP profile- to create the list in the YouTube channel related to that account.

But that's not the way I want my website to work: I want all of the users to create all of their lists in my YouTube channel. And only in mine.

So I need that any request the API receives from my website is authorized via the Gmail account related to my YouTube channel exclusively. Moreover, that way the authorization process would become invisible to the user, which it's an advantage. I want them to create their lists by just clicking a single button in my website.

I've been suggested to do all of this server-side -PHP in my case- using a service account, but reading the library docs I've found this:

https://github.com/googleapis/google-api-php-client#authentication-with-service-accounts

Some APIs (such as the YouTube Data API) do not support service accounts.

So... Do I have any other option to automate the authorization process?



from Accessing YouTube Data API without user intervention

Sort list by multiple fields and multiple criteria

I have the following code:

list.sort(Comparator
    .comparing(ProgrammData::getEnd)
    .thenComparing(ProgrammData::getStart).reversed());

My problem is that I want to have my list sorted by multiple things: 1.) Group them into future events and past events (By checking if the System.currentMilliseconds() is larger than the end timestamp) 2.) Sort future events by start ascending 3.) Sort past events by end descending

Can I do this with Java 8 Lambda or do I need another way of sorting the items?



from Sort list by multiple fields and multiple criteria

How can I remove the service name prefix in PyCharm when using the docker-compose interpreter type?

I have created a simple app using docker-compose and its PyCharm support. I've configured a docker-compose interpreter using PyCharm's GUI. I want to run a pytest test using that interpreter, and enter the debugger. The problem is that when I enter the debugger, the service name (app_1) is prepended to all of the container output. This makes it very hard to read the session.

Recreating docker-compose-demo_app_1 ... 
Attaching to docker-compose-demo_app_1
Connected to pydev debugger (build 213.5744.248)
app_1  | Launching pytest with arguments test_foo.py::test_foo --no-header --no-summary -q in /opt/project
app_1  | 
app_1  |app_1  | ============================= test session starts ==============================
app_1  | collecting ... collected 1 item
app_1  |app_1  | 
app_1  | test_foo.py::test_foo ##teamcity[testSuiteStarted timestamp='2022-02-15T16:20:52.396' locationHint='python</opt/project>://test_foo' name='test_foo' nodeId='1' parentNodeId='0']
app_1  |>>> 42
app_1  | PyDev console: starting.
app_1  | 
app_1  | 42
>>> 

Here I've evaluated the expression 42, you can see my text entered after the prompt.

I see that docker-compose logs has a --no-log-prefix option that can apparently hide these logs, but as the interpreter configuration in PyCharm doesn't seem to expose any way to pass options to docker-compose, I don't know if I can use this option. Is there any way to get a cleaner output at the console?



from How can I remove the service name prefix in PyCharm when using the docker-compose interpreter type?

Monday 21 February 2022

Ways to stop other android applications from identifying my application?

We have developed a payment application with native android to compete in the local market. Our competitors have made it so that when their applications detect ours, theirs automatically disables itself. The problem is that our users use their applications as well so we wanted our application to be unidentifiable by the other apps. Our solutions for this have been distributing our app manually instead of playstore and generating a unique bundle id for each individual user.

What else can we do to get around this?



from Ways to stop other android applications from identifying my application?

Pass data from the model to js for a specific day and time

I have a model in which we can choose the opening hours of the institution for each day of the week, from such and such to such and such, for example Monday 12:00 AM - 11:30 PM

<?php

namespace common\models;

use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use yii\db\Expression;

class WorkHours extends _source_WorkHours
{
    public const WEEK_DAY_MON = 'Mon';
    public const WEEK_DAY_TUE = 'Tue';
    public const WEEK_DAY_WED = 'Wed';
    public const WEEK_DAY_THU = 'Thu';
    public const WEEK_DAY_FRI = 'Fri';
    public const WEEK_DAY_SAT = 'Sat';
    public const WEEK_DAY_SUN = 'Sun';


    /**
     * {@inheritdoc}
     */
    public function behaviors(): array
    {
        return [
            'timestamp' => [
                'class'      => TimestampBehavior::class,
                'attributes' => [
                    ActiveRecord::EVENT_BEFORE_INSERT => ['created_at'],
                ],
                'value'      => new Expression('NOW()'),
            ],
        ];
    }

    public static function weekDays(): array
    {
        return [
            self::WEEK_DAY_MON => 'Monday',
            self::WEEK_DAY_TUE => 'Tuesday',
            self::WEEK_DAY_WED => 'Wednesday',
            self::WEEK_DAY_THU => 'Thursday',
            self::WEEK_DAY_FRI => 'Friday',
            self::WEEK_DAY_SAT => 'Saturday',
            self::WEEK_DAY_SUN => 'Sunday',
        ];
    }

    public static function getWeekDay(string $val): string
    {
        $ar = self::weekDays();

        return $ar[$val] ?? $val;
    }

    public static function hoursList(): array
    {
        $list = [];
        for ($i = 0; $i < 24; $i++) {
            $A = 'AM';
            $n = $i;
            if ($i >= 12) {
                $A = 'PM';
                $n = $i - 12;
            }

            $n = $n < 10 ? '0' . $n : $n;
            $_A = ($i === 12 ? 'AM' : $A);
            $list[$i . '.00'] = $n . '.00 ' . ($i === 0 ? 'PM' : $_A);
            $list[$i . '.30'] = $n . '.30 ' . $A;
        }
        return $list;
    }
}

Next, using the script, we pass all these fields, and in the end we can select any day, at any time, from 00:00 PM to 11:30 PM

$this->registerJsFile('/js/restaurant-reserve.js', ['depends' => [JqueryAsset::class]]);
$this->registerJs('restaurantReserve.init()');

<a class="btn btn-fourth <?= $restaurantReservationForm->getErrors('date') ? 'btn-error' : '' ?>" id="reservation-date" data-date="<?= $restaurantReservationForm->getDate()
                   ? $restaurantReservationForm->getDate()->format('m/d/Y') : '' ?>>">
  <span class="icon br-calender"></span> <span class="js-value">
                    <?= $restaurantReservationForm->date
                        ? (new DateTime($restaurantReservationForm->date))->format('d M') : '-- ---' ?>
                </span>
</a>
<a class="btn btn-fourth <?= $restaurantReservationForm->getErrors('time') ? 'btn-error' : '' ?>" id="reservation-time" role="button" data-bs-toggle="dropdown" aria-expanded="false">
  <span class="icon br-clock"></span> <span class="js-value">
                    <?= $restaurantReservationForm->time
                        ? WorkHours::hoursList()[$restaurantReservationForm->time] : '-- : --' ?>
                </span>
</a>
<ul class="dropdown-menu dropdown-menu-height-fixed" aria-labelledby="reservation-time">
  <?php foreach (WorkHours::hoursList() as $k => $v) { ?>
    <li>
      <a class="dropdown-item <?= $restaurantReservationForm->time === $k ? 'active' : ''
                        ?>" href="#" data-value="<?= $k ?>">
        <?= $v ?>
      </a>
    </li>
    <?php } ?>
</ul>

Here is the script

let restaurantReserve = {
    init: function () {
        let _self = this;

        $('#reservation-date').datepicker({startDate: '+0d'}).on('changeDate', function (e) {
            const arDate = e.date.toString().split(' ');
            let input = $('[name="RestaurantReservationForm[date]"]');
            input.val(arDate[3] + '-' + (e.date.getMonth() + 1) + '-' + arDate[2]);
            _self.unSetError(input);
            $('#reservation-date .js-value').text(arDate[2] + ' ' + arDate[1]);
        });

        $('[aria-labelledby="reservation-time"] li a').click(function () {
            $(this).closest('ul').find('a').removeClass('active');
            $(this).addClass('active');
            let input = $('[name="RestaurantReservationForm[time]"]');
            input.val($(this).data('value'));
            _self.unSetError(input);
            $('#reservation-time .js-value').text($(this).text());
        });

        $('[aria-labelledby="reservation-person"] li a').click(function () {
            $(this).closest('ul').find('a').removeClass('active');
            $(this).addClass('active');
            let input = $('[name="RestaurantReservationForm[personCount]"]');
            input.val($(this).data('value'));
            _self.unSetError(input);
            $('#reservation-person .js-value').text($(this).data('value'));
        });
    },
    setError: function (ob) {
        $('#' + ob.data('btnId')).addClass('btn-error');
    },
    unSetError: function (ob) {
        $('#' + ob.data('btnId')).removeClass('btn-error');
    }
}

I have different establishments and each establishment has its own working hours. And I need to have a choice of time for a particular institution on a particular day. Let's say one establishment on Monday has a working time from 9:30 AM to 2.30 PM, as a result, the select should have a choice of time only in this interval.

What am I trying to do

To begin with, pass data from the database to the init function via json

$this->registerJs('restaurantReserve.init('. Json::encode($restaurant->workHours) .')');

As a result, we pass data to the script in the form of an array with a database [{"id":"1","restaurant_id":"1","day":"Mon","open":"9.30","close":"14.30","created_at":"2022-02-15 05:00:57"}]

Here's the plug, I have the necessary data, it remains only to add the script so that for each day there is a time interval taken from this data

I need another function like

restaurantDate: function (e) {
        .....
    }

But what to do in it, I still do not quite understand

let restaurantReserve = {
    init: function () {
        let _self = this;

        $('#reservation-date').datepicker({startDate: '+0d'}).on('changeDate', function (e) {
            const arDate = e.date.toString().split(' ');
            let input = $('[name="RestaurantReservationForm[date]"]');
            input.val(arDate[3] + '-' + (e.date.getMonth() + 1) + '-' + arDate[2]);
            _self.unSetError(input);
            $('#reservation-date .js-value').text(arDate[2] + ' ' + arDate[1]);
        });

        $('[aria-labelledby="reservation-time"] li a').click(function () {
            $(this).closest('ul').find('a').removeClass('active');
            $(this).addClass('active');
            let input = $('[name="RestaurantReservationForm[time]"]');
            input.val($(this).data('value'));
            _self.unSetError(input);
            $('#reservation-time .js-value').text($(this).text());
        });

        $('[aria-labelledby="reservation-person"] li a').click(function () {
            $(this).closest('ul').find('a').removeClass('active');
            $(this).addClass('active');
            let input = $('[name="RestaurantReservationForm[personCount]"]');
            input.val($(this).data('value'));
            _self.unSetError(input);
            $('#reservation-person .js-value').text($(this).data('value'));
        });
    },
    setError: function (ob) {
        $('#' + ob.data('btnId')).addClass('btn-error');
    },
    unSetError: function (ob) {
        $('#' + ob.data('btnId')).removeClass('btn-error');
    }
}
.btn {
    border: none;
    border-radius: 8px;
    height: 40px;
    padding: 10px 15px;
    font-weight: 800;
    font-size: 14px;
    margin-right: 10px;
    cursor: pointer;
}

.btn-fourth {
    text-decoration: none;
    background: #e3e5e8;
    color: #747b8b;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="reservation" action="/restaurants/123/" method="post">
   <div class="block-shadow block-white mb-4">
        <h5 class="fw-bold mb-3">Reserve a table</h5>
        <div class="btn-s">
            <a class="btn btn-fourth "
               id="reservation-date"
               data-date=">">
                <span class="icon br-calender"></span> <span class="js-value">
                    -- ---                </span>
            </a>
            <a class="btn btn-fourth "
               id="reservation-time" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                <span class="icon br-clock"></span> <span class="js-value">
                    -- : --                </span>
            </a>
            <ul class="dropdown-menu dropdown-menu-height-fixed" aria-labelledby="reservation-time">
                                    <li><a class="dropdown-item " href="#" data-value="0.00">00.00 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="0.30">00.30 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="1.00">01.00 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="1.30">01.30 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="2.00">02.00 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="2.30">02.30 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="3.00">03.00 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="3.30">03.30 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="4.00">04.00 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="4.30">04.30 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="5.00">05.00 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="5.30">05.30 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="6.00">06.00 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="6.30">06.30 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="7.00">07.00 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="7.30">07.30 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="8.00">08.00 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="8.30">08.30 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="9.00">09.00 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="9.30">09.30 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="10.00">10.00 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="10.30">10.30 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="11.00">11.00 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="11.30">11.30 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="12.00">00.00 AM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="12.30">00.30 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="13.00">01.00 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="13.30">01.30 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="14.00">02.00 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="14.30">02.30 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="15.00">03.00 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="15.30">03.30 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="16.00">04.00 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="16.30">04.30 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="17.00">05.00 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="17.30">05.30 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="18.00">06.00 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="18.30">06.30 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="19.00">07.00 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="19.30">07.30 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="20.00">08.00 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="20.30">08.30 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="21.00">09.00 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="21.30">09.30 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="22.00">10.00 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="22.30">10.30 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="23.00">11.00 PM</a></li>
                                    <li><a class="dropdown-item " href="#" data-value="23.30">11.30 PM</a></li>
                            </ul>
        </div>
        <div class="form-group field-restaurantreservationform-personcount">
<input type="hidden" id="restaurantreservationform-personcount" class="form-control" name="RestaurantReservationForm[personCount]" data-btn-id="reservation-person">
</div>        <div class="form-group field-restaurantreservationform-date required">
<input type="hidden" id="restaurantreservationform-date" class="form-control" name="RestaurantReservationForm[date]" data-btn-id="reservation-date">
</div>        <div class="form-group field-restaurantreservationform-time">
<input type="hidden" id="restaurantreservationform-time" class="form-control" name="RestaurantReservationForm[time]" data-btn-id="reservation-time">
</div>        <div class="form-group field-restaurantreservationform-name required">
<label class="control-label" for="restaurantreservationform-name">Your Name</label>
<input type="text" id="restaurantreservationform-name" class="form-control" name="RestaurantReservationForm[name]" aria-required="true">

<p class="help-block help-block-error"></p>
</div>        <div class="form-group field-restaurantreservationform-emailphone required">
<label class="control-label" for="restaurantreservationform-emailphone">Email Address or Phone Number</label>
<input type="text" id="restaurantreservationform-emailphone" class="form-control" name="RestaurantReservationForm[emailPhone]" aria-required="true">


from Pass data from the model to js for a specific day and time