<commit_before>package com.intellij.stats.completion.experiment

import com.google.gson.Gson
import com.google.gson.internal.LinkedTreeMap
import com.intellij.ide.util.PropertiesComponent
import com.intellij.openapi.updateSettings.impl.UpdateChecker
import com.intellij.stats.completion.RequestService
import com.intellij.stats.completion.assertNotEDT

class StatusInfoProvider(private val requestSender: RequestService) {

    companion object {
        private val gson = Gson()

        private val statusUrl = "https://www.jetbrains.com/config/features-service-status.json"

        private val salt = "completion.stats.experiment.salt"
        private val experimentVersionString = "completion.stats.experiment.version"
    }

    @Volatile private var statusInfo = loadInfo()
    @Volatile private var serverStatus = ""
    @Volatile private var dataServerUrl = ""

    fun getExperimentVersion() = statusInfo.experimentVersion
    
    fun getDataServerUrl(): String = dataServerUrl
    
    fun isServerOk(): Boolean = serverStatus.equals("ok", ignoreCase = true)
    
    fun isPerformExperiment(): Boolean {
        val uid = UpdateChecker.getInstallationUID(PropertiesComponent.getInstance())
        val hash = (uid + statusInfo.salt).hashCode()
        return hash % 2 == 0
    }
    
    fun updateStatus() {
        serverStatus = ""
        dataServerUrl = ""
        
        assertNotEDT()
        val response = requestSender.get(statusUrl)
        if (response != null && response.isOK()) {
            val map = gson.fromJson(response.text, LinkedTreeMap::class.java)
            
            val salt = map["salt"]?.toString()
            val experimentVersion = map["experimentVersion"]?.toString()
            if (salt != null && experimentVersion != null) {
                //should be Int always
                val floatVersion = experimentVersion.toFloat()
                statusInfo = ExperimentInfo(floatVersion.toInt(), salt)
                saveInfo(statusInfo)
            }
            
            serverStatus = map["status"]?.toString() ?: ""
            dataServerUrl = map["url"]?.toString() ?: ""
        }
    }

    private fun loadInfo(): ExperimentInfo {
        val component = PropertiesComponent.getInstance()
        val salt = component.getValue(salt) ?: ""
        val experimentVersion = component.getInt(experimentVersionString, 0)
        return ExperimentInfo(experimentVersion, salt)
    }

    private fun saveInfo(info: ExperimentInfo) {
        val component = PropertiesComponent.getInstance()
        component.setValue(salt, info.salt)
        component.setValue(experimentVersionString, info.experimentVersion.toString())
    }

}

data class ExperimentInfo(var experimentVersion: Int, var salt: String) {
    constructor() : this(0, "")
}<commit_msg>use url for zipped content<commit_after>package com.intellij.stats.completion.experiment

import com.google.gson.Gson
import com.google.gson.internal.LinkedTreeMap
import com.intellij.ide.util.PropertiesComponent
import com.intellij.openapi.updateSettings.impl.UpdateChecker
import com.intellij.stats.completion.RequestService
import com.intellij.stats.completion.assertNotEDT

class StatusInfoProvider(private val requestSender: RequestService) {

    companion object {
        private val gson = Gson()

        private val statusUrl = "https://www.jetbrains.com/config/features-service-status.json"

        private val salt = "completion.stats.experiment.salt"
        private val experimentVersionString = "completion.stats.experiment.version"
    }

    @Volatile private var statusInfo = loadInfo()
    @Volatile private var serverStatus = ""
    @Volatile private var dataServerUrl = ""

    fun getExperimentVersion() = statusInfo.experimentVersion
    
    fun getDataServerUrl(): String = dataServerUrl
    
    fun isServerOk(): Boolean = serverStatus.equals("ok", ignoreCase = true)
    
    fun isPerformExperiment(): Boolean {
        val uid = UpdateChecker.getInstallationUID(PropertiesComponent.getInstance())
        val hash = (uid + statusInfo.salt).hashCode()
        return hash % 2 == 0
    }
    
    fun updateStatus() {
        serverStatus = ""
        dataServerUrl = ""
        
        assertNotEDT()
        val response = requestSender.get(statusUrl)
        if (response != null && response.isOK()) {
            val map = gson.fromJson(response.text, LinkedTreeMap::class.java)
            
            val salt = map["salt"]?.toString()
            val experimentVersion = map["experimentVersion"]?.toString()
            if (salt != null && experimentVersion != null) {
                //should be Int always
                val floatVersion = experimentVersion.toFloat()
                statusInfo = ExperimentInfo(floatVersion.toInt(), salt)
                saveInfo(statusInfo)
            }
            
            serverStatus = map["status"]?.toString() ?: ""
            dataServerUrl = map["urlForZipBase64Content"]?.toString() ?: ""
        }
    }

    private fun loadInfo(): ExperimentInfo {
        val component = PropertiesComponent.getInstance()
        val salt = component.getValue(salt) ?: ""
        val experimentVersion = component.getInt(experimentVersionString, 0)
        return ExperimentInfo(experimentVersion, salt)
    }

    private fun saveInfo(info: ExperimentInfo) {
        val component = PropertiesComponent.getInstance()
        component.setValue(salt, info.salt)
        component.setValue(experimentVersionString, info.experimentVersion.toString())
    }

}

data class ExperimentInfo(var experimentVersion: Int, var salt: String) {
    constructor() : this(0, "")
}
{'fraction_non_alphanumeric': 0.10144927536231885, 'fraction_numerical': 0.0017674089784376105, 'mean_word_length': 2.841819416157502, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2774626', 'n_tokens_mistral': 1511, 'n_tokens_neox': 1455, 'n_words': 318}