AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / 问题

All perguntas(coding)

Martin Hope
redoc01
Asked: 2025-04-09 23:37:27 +0800 CST

Comparar um termo de pesquisa que contém mais de uma palavra e pesquisar diferentes variações do termo de pesquisa e extrair registros

  • 6

Se eu tiver um termo de pesquisa que seja igual a "Olá Connor Mcgregor", como eu usaria esse termo de pesquisa para que ele repetisse cada palavra de pesquisa na lista, por exemplo:

searchTerm[0] = "Hello";
searchTerm[1] = "Conner"
searchTerm[2] = "Mcgregor"

e pesquisa cada valor separado por um espaço com um campo ou com dois campos na tabela e retorna essa linha.

Nos últimos anos, tenho usado o EntityFramework, mas tenho tentado isso no LINQ e descobri que é melhor usar o ADO.NET e um procedimento armazenado.

O que foi tentado:

    DECLARE @pos INT
    DECLARE @len INT
    DECLARE @value nvarchar(80)
    DECLARE @sql nvarchar(max)

    set @pos = 0
    set @len = 0

    WHILE CHARINDEX(' ', @searchTerm, @pos+1) > 0
    BEGIN
            set @len = CHARINDEX(',', @searchTerm, @pos+1) - @pos
            set @value = SUBSTRING(@searchTerm, @pos, @len)            

             if exists (select title, questionText from tblThread where title like @value + '%')
             BEGIN
                set @sql = (select title, questionText from tblThread where title like @value + '%')
                Print @sql
                --DO YOUR MAGIC HERE        
             END
            set @pos = CHARINDEX(',', @searchTerm, @pos+@len) +1
    END 

Eu tentei isso, mas não consigo adicionar os valores na tabela temporária

ALTER PROCEDURE [dbo].[getThreadsBySearchTerm] 

    @searchTerm nvarchar(80)

AS
BEGIN
SET NOCOUNT ON;

    
    DECLARE @searchTermTbl TABLE (searchTerm nvarchar(max))
    DECLARE @value nvarchar(max)
    DECLARE @pos INT
    DECLARE @len INT
    DECLARE @sql nvarchar(max)

    DECLARE @sqlWithSpace Int

    set @pos = 0
    set @len = 0

    

    while CHARINDEX(' ', @searchTerm, @pos+1) > 0
    Begin
            set @len = CHARINDEX(' ', @searchTerm, @pos+1) - @pos
            set @value = SUBSTRING(@searchTerm, @pos, @len)            

            insert into @searchTermTbl values(@value)
            set @pos = CHARINDEX(' ', @searchTerm, @pos+@len) +1

    End 
     

     
    if exists(select * from @searchTermTbl)
        begin
            select title, questionText from tblThread
            inner join @searchTermTbl stt on tblThread.title Like '%' + stt.searchTerm + '%'
            inner join @searchTermTbl sttt on tblThread.questionText Like '%' + sttt.searchTerm + '%'
        end
    else
        begin
            select title, questionText from tblThread
            where title like '%' + @searchTerm + '%'
            or questionText like '%' + @searchTerm + '%'
        end

    select * from @searchTermTbl
END
GO


exec getThreadsBySearchTerm 'Question is'

está adicionando "Pergunta", mas não "é"

sql
  • 1 respostas
  • 71 Views
Martin Hope
Lamens
Asked: 2025-04-09 23:28:10 +0800 CST

Como armazenar com segurança um refresh_token no frontend ao usar laravel/passport?

  • 6

Estou trabalhando em um fluxo OAuth 2.0 usando Authorization Code Grant com PKCE, envolvendo dois servidores locais:

  • https://sso-identify.test (servidor SSO)
  • https://cookie-1.test (Aplicação web front-end)

O que implementei:

O frontend redireciona o usuário para autorização e depois retorna a chamada para /auth/callback.

No retorno de chamada, troco o código de autorização por tokens de acesso e atualização usando um /oauth/tokensendpoint dedicado em sso-identify.test.

Laravel responde com:

{
  "access_token": "...",
  "refresh_token": "...",
  "expires_in": "..."
}

Nesse caso, o JS terá acesso ao refresh_token.

Como armazeno o refresh_token?

  • 1 respostas
  • 78 Views
Martin Hope
RJ Irv
Asked: 2025-04-09 23:13:46 +0800 CST

Como formatar caixa de painel com rolagem vertical?

  • 7

Para contextualizar, estou tentando converter um painel existente do PowerBI em um painel do RShiny com funcionalidade equivalente ou quase equivalente.

Basicamente, tenho um gráfico de barras horizontais com muitas categorias. Um problema secundário é que todos os meus gráficos de barras no RShiny parecem estar justificados à direita dentro de suas caixas.

Estou tentando descobrir como fazer com que o gráfico de barras seja exibido em tamanho real, permitindo uma rolagem vertical, em vez de deixá-lo muito pequeno para caber na caixa estática.

Tentei corrigir a altura da caixa, o que pensei que criaria automaticamente uma barra de rolagem vertical. A imagem

insira a descrição da imagem aqui

mostra o que estou tentando recriar em conceito, onde as barras são em escala horizontal e a caixa permite rolagem vertical. No entanto, continuo com o gráfico completo super pequeno, todo amontoado na caixa.

insira a descrição da imagem aqui

e também justificado à direita. Abaixo está o código do servidor e da interface do usuário para este gráfico específico.

library(shiny)
library(shinydashboard)
library(tidyverse)
library(plotly)

ae <- structure(list(aept = c("Upper respiratory tract infection", 
                              "Fungal infection", "COVID-19", "COVID-19", "Anxiety", "Weight increased", 
                              "Hyperlipidaemia", "Hyperglycaemia", "Influenza", "Neck pain", 
                              "Electrocardiogram QT prolonged", "Irritability", "Headache", 
                              "Contusion", "Headache", "Headache", "Headache", "Anaemia", "Candida infection", 
                              "Headache", "Headache", "Headache", "Upper respiratory tract infection", 
                              "Diarrhoea", "COVID-19", "Influenza", "Electrocardiogram T wave abnormal", 
                              "Headache", "Headache", "Headache", "Diarrhoea", "Upper respiratory tract infection", 
                              "Headache", "Vaginal infection", "Tonsillitis bacterial", "Peritonsillar abscess", 
                              "Atrioventricular block first degree", "Procedural dizziness", 
                              "Influenza", "Procedural dizziness", "Viral infection", "Diarrhoea", 
                              "Nausea", "Rhinitis", "Diarrhoea", "Upper respiratory tract infection", 
                              "Diarrhoea", "Upper respiratory tract infection", "Headache", 
                              "Rhinitis", "Upper respiratory tract infection", "Gamma-glutamyltransferase increased", 
                              "Gamma-glutamyltransferase increased", "Headache", "Headache", 
                              "Headache", "Insomnia", "", "", "Headache", "Glomerular filtration rate decreased", 
                              "Blood creatinine increased", "Headache", "Ear pain", "Headache", 
                              "Headache", "Rhinitis allergic", "Oropharyngeal pain", "Headache", 
                              "Diarrhoea", "Headache", "Headache", "Headache", "Urinary tract infection", 
                              "Headache", "Vaginal discharge", "Anaemia", "Influenza", "Bronchitis", 
                              "Upper respiratory tract infection", "Rhinitis", "Blood thyroid stimulating hormone decreased", 
                              "Abdominal pain upper", "Headache", "Tonsillitis", "Headache", 
                              "Headache", "Methaemoglobinaemia", "Abdominal pain", "Abdominal pain lower", 
                              "Blood creatine phosphokinase increased", "Electrocardiogram QT prolonged", 
                              "Headache", "Headache", "Electrocardiogram QT prolonged", "Electrocardiogram QT prolonged", 
                              "Headache", "Headache", "Upper respiratory tract infection", 
                              "Upper respiratory tract infection")), row.names = c(NA, 100L
                              ), class = "data.frame")

server <- function(input, output){
  #AE Preferred Term 
  output$ae_pt <- renderPlotly({
    p <- ae %>% group_by(aept) %>% summarise(count=n()) %>% arrange(desc(count)) %>% 
      ggplot(aes(x=reorder(aept,count), y=count)) +
      geom_bar(stat='identity') +
      coord_flip() +
      theme_minimal()
    ggplotly(p)
  })
}


ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(
    sidebarMenu(
      menuItem("Adverse Events", tabName = "ae", icon = icon("heart"))
    )),
  
  dashboardBody(
    tabItems(
      # Adverse Events Tab ----
      tabItem(tabName="ae",
              #AE PT and .....
              fluidRow(box(plotlyOutput("ae_pt"),title="Preferred Term"))
      )
    )))

shinyApp(ui, server)
  • 1 respostas
  • 40 Views
Martin Hope
knods
Asked: 2025-04-09 23:05:20 +0800 CST

Existe alguma maneira de evitar clonagens/alocações repetidas neste método Runge-Kutta-Fehlberg?

  • 8

Estou implementando o método Runge-Kutta-Fehlberg 5(4) em Rust, então tenho que monitorar o estado atual do sistema que estou tentando modelar, executar vários cálculos com base no estado atual e, como resultado desses cálculos, atualizar o estado.

No processo, me deparei com problemas de propriedade, porque o nalgebratipo que estou usando não implementa copy. O compilador sugeriu que eu cloneusasse os dados. Acabei com quatro .clone()instruções dentro de um loop e estou pensando sobre o impacto no desempenho, por um lado, e possíveis alternativas, por outro.

Você pode encontrar a função relevante abaixo.

pub fn rkf54(
    initial_time: f64,
    initial_state: State<f64>,
    initial_step_size: f64,
    control: bool,
    tolerance: f64,
    final_time: f64,
    f: &dyn Fn(f64, &State<f64>) -> State<f64>)
    -> Vec<State<f64>> {

    let mut output: Vec<State<f64>> = vec![];

    let mut time = initial_time;
    let mut state = initial_state;
    let mut step_size = initial_step_size;

    while time < final_time  {
        if control {
            // CLONE 1
            step_size = rkf_control(time, state.clone(), initial_step_size, tolerance, f);
        }
        
        // CLONE 2
        let stages = rkf_stages(time, &state.clone(), step_size, A, C, f);

        // CLONE 3
        state = rkf_step(&state.clone(), step_size, &stages, B_PRIMARY);
        time += step_size;


        // CLONE 4
        output.push(state.clone())
    }
    let stages = rkf_stages(final_time, &state.clone(), step_size, A, C, f);
    state = rkf_step(&state.clone(), step_size, &stages, B_PRIMARY);
    output.push(state.clone());

return output;
}

A clonagem repetida afetará significativamente o desempenho? Se entendi corretamente, isso copia os mesmos dados de e para diferentes áreas da memória 4 vezes por iteração.

Se sim, como posso evitar esse tipo de clonagem/alocação?

Aqui está um exemplo funcional completo, juntamente com definições de tipo e constante.

#![allow(dead_code)]

extern crate nalgebra; // 0.33.2

use nalgebra::DVector; // 0.33.2
use std::f64::INFINITY;

type Stages<T, const D: usize> = [DVector<T>; D];
pub type State<T> = DVector<T>;
pub type StageCoefficients<T, const D: usize> = [&'static [T]; D];
pub type Weights<T, const D: usize> = [T; D];

pub const A: StageCoefficients<f64, 6> = [
    &[],
    &[1./4.],
    &[3./32.,       9./32.],
    &[1932./2197.,  -7200./2197.,   7296./2197.],
    &[439./216.,    8.,             3680./513.,     -845./4104.],
    &[-8./27.,      2.,             -3544./2565.,   1859./4104.,    -11./40.]
];

pub const C: Weights<f64, 6> =  [0.0,           1./4.,          3./8.,          12./13.,        1.,         1./2.   ];
pub const B_PRIMARY: Weights<f64, 6> =  [16./135.,      0.,             6656./12825.,   28561./56430.,  -9./50.,    2./55.  ];
pub const B_EMBEDDED: Weights<f64, 6> =     [25./216.,      0.,             1408./2565.,    2197./4104.,    -1./5.,     0.      ];


const K: f64 = 0.02;
const B0: f64 = 3.5;
const B1: f64 = 16.72;

pub fn f(t:f64, state: &State<f64>) -> State<f64> {   
    let x = state[0];
    let y = state [1];
    
    let x_dot = y;
    let y_dot = (-K*y) - (x.powf(3.)) + (B0) + (B1 * t.cos());

    return State::from(vec![x_dot, y_dot]);
}

pub fn rkf54(
    initial_time: f64,
    initial_state: State<f64>,
    initial_step_size: f64,
    control: bool,
    tolerance: f64,
    final_time: f64,
    f: &dyn Fn(f64, &State<f64>) -> State<f64>)
    -> Vec<State<f64>> {

    let mut output: Vec<State<f64>> = vec![];

    let mut time = initial_time;
    let mut state = initial_state;
    let mut step_size = initial_step_size;

    while time < final_time  {
        if control {
            // CLONE 1
            step_size = rkf_control(time, state.clone(), initial_step_size, tolerance, f);
        }
        
        // CLONE 2
        let stages = rkf_stages(time, &state.clone(), step_size, A, C, f);

        // CLONE 3
        state = rkf_step(&state.clone(), step_size, &stages, B_PRIMARY);
        time += step_size;


        // CLONE 4
        output.push(state.clone())
    }
    let stages = rkf_stages(final_time, &state.clone(), step_size, A, C, f);
    state = rkf_step(&state.clone(), step_size, &stages, B_PRIMARY);
    output.push(state.clone());

return output;
}
fn rkf_stages<const D: usize>(
    time: f64,
    state: &State<f64>,
    step_size: f64,
    stage_coefficients: StageCoefficients<f64, D>,
    time_fractions: Weights<f64, D>,
    f: &dyn Fn(f64, &State<f64>) -> State<f64>
    ) -> Stages<f64, D> {

    let mut k: Stages<f64, D> = std::array::from_fn(|_| DVector::zeros(state.nrows()));
    
    for i in 0..stage_coefficients.len() {
        let mut x: State<f64> = DVector::zeros(state.nrows());
        for j in 0..stage_coefficients[i].len() {
            x += &k[j] * stage_coefficients[i][j];
        }
        x = state + step_size*(x);
        let t = time + (step_size*time_fractions[i]);
        k[i] = f(t,&x);
    }

    return k;
}

fn rkf_step<const D: usize>(state: &State<f64>, step_size: f64, stages: &Stages<f64, D>, weights: Weights<f64, D>) -> State<f64> {
    
    let mut x_out = 0.0 * DVector::zeros(state.nrows());

    for i in 0..A.len() {
        x_out += &stages[i] * weights[i];
    }
    x_out *= step_size;
    x_out += state;
    
    return x_out;
}

fn rkf_control(time: f64, state: State<f64>, initial_step_size: f64, tolerance: f64,
    f: &dyn Fn(f64, &State<f64>) -> State<f64>) -> f64 {

    let mut error_estimate = INFINITY;
    let mut step_size = initial_step_size;

    while error_estimate > tolerance {
        let k = rkf_stages(time, &state, step_size, A, C, f);
        let x_primary = rkf_step(&state, step_size, &k, B_PRIMARY);
        let x_embedded = rkf_step(&state, step_size, &k, B_EMBEDDED);

        error_estimate = (x_primary - x_embedded).norm();
        step_size = 0.9 * step_size * (tolerance / error_estimate).powf(1. / 5.);
    }

    return step_size;
}

fn main() {
    let initial_time = 0.;
    let initial_state = State::from(vec![2., 2.]);
    let initial_step_size = 1.;
    let control = true;
    let tolerance = 10e-3;
    let final_time = 1.;

    let output = rkf54(initial_time, initial_state, initial_step_size, control, tolerance, final_time, &f);
    for state in output {
        println!("{state:1.3e}");
    }

}
rust
  • 1 respostas
  • 151 Views
Martin Hope
user2454324
Asked: 2025-04-09 22:38:41 +0800 CST

Validação condicional Zod com base em dados obtidos

  • 6

Estou buscando os valores tsmin e tsmax da API GET. Defini um esquema zod com validação gte.

  const tsmin = Number(getMinMechProp("tensilestrength"));
  const tsmax = Number(getMaxMechProp("tensilestrength"));

 const mechPropSchema = z.object({
   tensilestrength: z.coerce.number()
      .gte(tsmin, `Value must be at least ${tsmin}`),
});

Agora quero aplicar a validação zod lte somente se tsmax > 0.

Não encontrei a melhor maneira de conseguir isso

reactjs
  • 1 respostas
  • 19 Views
Martin Hope
Mohammad Si Abbou
Asked: 2025-04-09 22:28:29 +0800 CST

Por que useRouter() sempre retorna indefinido na minha biblioteca

  • 5

Tenho uma biblioteca vue.js que supostamente é bem simples, só tenho uma função personalizada para criar um aplicativo Vue como esta:

import AppComp from "./components/App.vue";

export const createMyCustomApp = (props): App<Element> => {
    console.log("Creating app with props: ", getNonEmptyProps(props));
    return createApp(AppComp , getNonEmptyProps(props));
}

e o App.vue:

<script setup lang="ts">
import {useRouter} from "vue-router";
import {useFetchingError, useIsFetching} from "../app";
import {ComputedRef, defineComponent, onMounted, PropType} from "vue";
import {computed, getCurrentInstance} from "vue";
import Loading from "./Loading.vue";
import Error from "./Error.vue";

defineProps({
  loadingComponent: {
    type: Object as PropType<ReturnType<typeof defineComponent>>,
    default: Loading
  },
  errorComponent: {
    type: Object as PropType<ReturnType<typeof defineComponent>>,
    default: Error
  }
});

const isFetching: ComputedRef<boolean> = computed(() => useIsFetching());
const fetchingError = computed(() => useFetchingError());

const router = useRouter();

console.log("=".repeat(50));
console.log("router : ", router);
console.log(getCurrentInstance());
console.log("=".repeat(50));

router.afterEach((to, from, failure) => {
  // some code
});


router.afterEach(() => /*some code*/);

onMounted(() => {
  const newRouter = useRouter();
  console.log("After nount" , newRouter);
});
</script>

<template>
  <component v-if="isFetching" :is="loadingComponent"/>
  <component v-if="fetchingError" :is="errorComponent" :error="fetchingError.message"/>
  <router-view v-else></router-view>
</template>

e eu tenho vuee vue-routercomo peerDependencies, este é meu pacote.json

{
  "name": "@myusername/redacted",
  "version": "0.0.2",
  "description": "something....",
  "main": "dist/lib.umd.js",
  "module": "dist/lib.es.js",
  "browser": "dist/lib.cjs.js",
  "types": "dist/app.d.ts",
  "exports": {
    "." : {
      "import": "./dist/lib.es.js",
      "require": "./dist/lib.cjs.js"
    }
  },
  "files": [
    "dist"
  ],
  "publishConfig": {
    "registry": "https://npm.pkg.github.com/@myusername"
  },
  "scripts": {
    "dev": "vite",
    "build": "vite build"
  },
  "keywords": [
    "client",
    "metaframework",
    "watchfulraven"
  ],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "vite": "^6.2.0",
    "vite-plugin-dts": "^4.5.0"
  },
  "peerDependencies": {
    "vue": "^3.5.13",
    "vue-router": "^4.5.0"
  },
  "dependencies": {
    "@vitejs/plugin-vue": "^5.2.1",
    "axios": "^1.8.1"
  }
}

e no meu vite.config.ts:

import {defineConfig} from "vite";
import dts from "vite-plugin-dts";
import vue from "@vitejs/plugin-vue";
export default defineConfig({
    build: {
        lib: {
            entry: "src/app.ts",
            name: "lib",
            formats: ["es", "cjs", "umd"],
            fileName: (format) => `lib.${format}.js`,
        },
        rollupOptions: {
            external: ['vue', 'vue-router'],
            output: {
                globals: {
                    vue: 'Vue',
                    'vue-router': 'VueRouter',
                },
            },
        },
    },
    plugins: [
        vue(),
        dts({rollupTypes: true})
    ]
});

e no meu app.js no meu aplicativo principal eu uso assim:

import {createMyCustomApp} from "@myusername/thepackagename";
import {router} from "@/presentation/routes/router.js";
import {i18n} from "./i18n.ts";


const app = createMyCustomApp({});

app
    .use(router)
    .use(i18n)
    .mount("#app");

mas como eu disse, o roteador console.log retorna indefinido e no meu console diz:

[Vue warn]: injeção "Symbol(router)" não encontrada em <App >

Se eu usar o mesmo componente App.vue, mas localmente, sem o pacote, ele também funciona bem. Passei muito tempo tentando fazê-lo funcionar. Qualquer ajuda seria apreciada.

vue.js
  • 1 respostas
  • 28 Views
Martin Hope
user30222843
Asked: 2025-04-09 22:22:42 +0800 CST

Sincronizando áudio com rolagem de partitura

  • 6

Estou construindo uma página da web que será usada por bateristas para praticar padrões.

Para isso, preciso ter:

  1. Um metrônomo ajustável (funcional)
  2. Uma partitura incluindo rolagem automática sincronizada com o metrônomo criada com tela HTML (não totalmente funcional)

O problema está na sincronização da rolagem da partitura com o metrônomo. Por enquanto, estou usando valores puramente empíricos, porque quando tentei calcular as distâncias e usei settimeout para rolar a partitura, não consegui um resultado satisfatório.

Observe:

  1. o espaço entre as notas é de 30 pixels.
  2. A tela provavelmente terá 100% da largura da página, como no exemplo.
  3. A barra vertical no meio da tela é o ponto de referência. Quando uma nota atinge essa barra, um som é reproduzido para que o usuário possa ouvir qual elemento da bateria deve ser tocado e como (volume máximo da caixa ou volume mínimo neste exemplo).

O script funciona, mas é bastante aproximado. Para que o script seja utilizável, deve haver uma sincronização muito boa entre o metrônomo e as notas que chegam ao compasso de referência.

Tentei calcular a distância que deve ser compensada a cada milissegundo, mas settimeout não permite menos que 15 a 17 ms e sua variação não é precisa o suficiente.

Abaixo está o código completo do projeto.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DrumChallenge.com</title>
    <style>
        #div_patterns {
            display: inline-block;
            margin: 20px;
        }
        #div_tempo {
            display: inline-block;
            margin: 20px;
        }
        #drumscore {
            position: relative;
            width: 100%;
            height: 200px;
        }
        #drumscore canvas {
            position: absolute;
            top: 0px;
            left: 0px;
        }
        canvas {
            border: 1px solid black;
            width: 100%;
            height: 200px;
        }
    </style>
</head>
<body>
    <div id="params">
        <div id="div_patterns"></div>
        <div id="div_tempo">
            <span>Tempo :</span>
            <input type="text" id="value_tempo" value="60" />
            
            <span>Delai :</span>
            <span id="value_delai"></span>
            
            <span>Timer :</span>
            <span id="value_timer"></span>
            
        </div>
        <button id="launch" class="launch" type="button">Lancer challenge</button>
    </div>
    <div id="drumscore">
        <canvas id="score"></canvas>
        <canvas id="scoreCanvas"></canvas>
    </div>
    <script src="metronome.js"></script>

    <script>
        
        
        
    document.addEventListener('DOMContentLoaded', () => {
        const audioContext = new (window.AudioContext || window.webkitAudioContext)();
        const metronome = new Metronome(audioContext);
        
        var Current_Audio = false;
        var Challenge_Launched = false;
        var Current_Animation = false;
        var Timer_Challenge = false;
        var Timer_General = false;
        var Tempo = 60;
        var Delai;
        var Distance_Between_Notes = 30;
        var General_Timer = 0;
        var NextNoteTime = 0;
        //
        //
        //
        const LaunchButton = document.getElementById('launch');
        LaunchButton.addEventListener('click', function(){
            if (Challenge_Launched == false){
                CreerChallenge();
                Challenge_Launched = true;
                
                const bpm = parseInt(InputTempo.value, 10);
                metronome.setTempo(bpm);
                metronome.start();
                
                Timer_General = setInterval(SetGeneralTimer, 1000);
                NextNoteTime = performance.now();
                //drawNotes();
                requestAnimationFrame(drawNotes);
            } else {
                Challenge_Launched = false;
                clearTimeout(Timer_Challenge);
                clearInterval(Timer_General);
                metronome.stop();
                //cancelAnimationFrame(Current_Animation);
            }
        });
        //
        //
        //
        function SetTempo(){
            Tempo = InputTempo.value;
            Delai = (60000 / Tempo).toFixed(2);
            document.getElementById('value_tempo').innerHTML = Tempo;
            document.getElementById('value_delai').innerHTML = Delai + 'ms';
            metronome.setTempo(Tempo);
            /*if (Challenge_Launched){
                clearTimeout(Timer_Challenge);
                //Timer_Challenge = setTimeout(drawNotes, Delai);
            }*/
        }
        //
        //
        //
        const InputTempo = document.getElementById('value_tempo');
        InputTempo.addEventListener('blur', function(){
            SetTempo()
        });
        SetTempo()
        //
        //
        //
        const drumscore = document.getElementById('drumscore');
        //
        // Canvas et contexte de la partition
        //
        const score = document.getElementById('score');
        const scorectx = score.getContext('2d');
        scorectx.canvas.width  = drumscore.offsetWidth;
        scorectx.canvas.height = drumscore.offsetHeight;
        //
        // Canvas et contexte des notes
        //
        const canvas = document.getElementById('scoreCanvas');
        const ctx = canvas.getContext('2d');
        ctx.canvas.width  = drumscore.offsetWidth;
        ctx.canvas.height = drumscore.offsetHeight;
        //
        // Lignes de la partition
        //
        const ScoreLines = [60,80,100,120,140];
        //
        //
        //
        const Elements = [
             {Name: 'Snare', Line: ScoreLines[2]}
        ];
        //
        // Patterns
        //
        const Patterns = [
            {
                Name:       'Rll',
                Element:    'Snare',
                Notes:      ['R', 'l', 'l'],
                Checkbox:   false,
                Label:      false,
                Checked:    false,
            },
            {
                Name:       'rrL',
                Element:    'Snare',
                Notes:      ['r', 'r', 'L'],
                Checkbox:   false,
                Label:      false,
                Checked:    false,
            }
        ];
        //
        // Affichage patterns
        //
        const DivPatterns = document.getElementById('div_patterns');
        Patterns.forEach(pattern => {
            pattern.Checkbox = document.createElement('input');
            pattern.Checkbox.type = "checkbox";

            pattern.Label = document.createElement('label')
            pattern.Label.htmlFor = pattern.Name;
            pattern.Label.appendChild(document.createTextNode(pattern.Name));
            
            DivPatterns.appendChild(pattern.Checkbox);
            DivPatterns.appendChild(pattern.Label);
        });
        //
        // Sounds
        //
        const Sounds = [
            {
                Element:    'Snare',
                Type:       'Normal',
                URL:        '',
                Audio:      new Audio('snare_normal.wav')
            },
            {
                Element:    'Snare',
                Type:       'Ghost',
                Audio:      new Audio('snare_ghost.wav')
            }
            
        ];
        //
        // Notes à afficher
        //
        
        const measures = 20;
        const noteWidth = 10;
        const noteHeight = 10;
        const scrollSpeed = 3;
        //
        // Main Droite ou Gauche
        //
        const isAccented = str => str === str.toUpperCase();
        const isRightHand = str => str.toUpperCase() === 'R';
        
        //
        // Créer le challenge
        //
        var notes = [];
        var current_pattern;
        //
        // Dessiner la partition
        //
        function CreerChallenge() {
            notes = [];
            for (var i=0 ; i<measures ; i++){
                current_pattern = Patterns[Math.floor(Math.random() * 2)];
                
                for (var j=0 ; j<current_pattern.Notes.length ; j++){
                    notes.push({
                        x:      canvas.width / 2 + 180 + (notes.length * Distance_Between_Notes) + 1,
                        y:      isRightHand(current_pattern.Notes[j]) ? ScoreLines[2] - 5 : ScoreLines[2] + 5,
                        w:      isAccented(current_pattern.Notes[j]) ? 7 : 4,
                        h:      isAccented(current_pattern.Notes[j]) ? 5 : 3,
                        Audio:  isAccented(current_pattern.Notes[j]) ? new Audio('snare_normal.wav') : new Audio('snare_ghost.wav')
                    })
                }
            }
            console.log(notes);
        }
        //
        // Dessiner la partition
        //
        function drawScore() {
            scorectx.clearRect(0, 0, canvas.width, canvas.height);
            scorectx.strokeStyle = "#A0A0A0";
            
            ScoreLines.forEach(Line => {
                scorectx.beginPath();
                scorectx.moveTo(0, Line);
                scorectx.lineTo(canvas.width, Line);
                scorectx.stroke();
            });
            
            scorectx.beginPath();
            scorectx.moveTo(canvas.width / 2, ScoreLines[0]);
            scorectx.lineTo(canvas.width / 2, ScoreLines[ScoreLines.length-1]);
            scorectx.stroke();
        }
        //
        //
        //
        function nextNote() {
            const secondsPerBeat = 60.0 / Tempo;
            NextNoteTime += 1000 / Distance_Between_Notes;
        }

        //
        // Dessiner et animer les notes
        //
        function drawNotes() {
            
            NextNoteTime = performance.now();
            
            ctx.clearRect(0, 0, canvas.width, canvas.height);

            notes.forEach(note => {
            
                //ctx.fillRect(note.x, note.y, note.w, note.w);
                ctx.beginPath();
                ctx.ellipse(note.x, note.y, note.w, note.h, Math.PI, 0, 2 * Math.PI);
                ctx.fill();
                
                if (note.x > canvas.width / 2 - 5 && note.x <= canvas.width / 2){
                    Current_Audio = note.Audio;
                    note.Audio.play();
                }
                
                //note.x -= scrollSpeed;
                note.x -= Tempo / 15;
            });

            
            //const endTime = performance.now()

            //console.log(`Call to doSomething took ${endTime - startTime} milliseconds ` + endTime)
            //Current_Animation = requestAnimationFrame(drawNotes);
            if (Challenge_Launched){
                //Timer_Challenge = setTimeout(drawNotes, 1);
                Timer_Challenge = setTimeout(() => requestAnimationFrame(drawNotes), 1);
            }
        }
        
        function SetGeneralTimer(){
            const startTime = performance.now()
            General_Timer++;
            document.getElementById('value_timer').innerHTML = General_Timer
            const endTime = performance.now()
            //console.log(`Started ` + startTime + ' | ' + (endTime - startTime) + ' | ' + General_Timer)
        }
        
        
        drawScore();
    });
    </script>
</body>
</html>

E a classe metrônomo:

class Metronome {
    constructor(context) {
        this.context = context;
        this.isPlaying = false;
        this.current16thNote = 0;
        this.tempo = 60;
        this.lookahead = 25.0;
        this.scheduleAheadTime = 0.1;
        this.nextNoteTime = 0.0;
        this.timerID = null;
    }

    nextNote() {
        const secondsPerBeat = 60.0 / this.tempo;
        this.nextNoteTime += 0.25 * secondsPerBeat;
        this.current16thNote++;
        if (this.current16thNote === 16) {
            this.current16thNote = 0;
        }
    }

    scheduleNote(beatNumber, time) {
        const osc = this.context.createOscillator();
        const envelope = this.context.createGain();
        osc.frequency.value = (beatNumber % 4 === 0) ? 1000 : 800;
        envelope.gain.value = 1;
        envelope.gain.exponentialRampToValueAtTime(0.001, time + 0.2);
        osc.connect(envelope);
        envelope.connect(this.context.destination);
        osc.start(time);
        osc.stop(time + 0.2);
    }

    scheduler() {
        console.log(this.nextNoteTime);
        console.log(this.context.currentTime);
        console.log(this.scheduleAheadTime);
        while (this.nextNoteTime < this.context.currentTime + this.scheduleAheadTime) {
            this.scheduleNote(this.current16thNote, this.nextNoteTime);
            this.nextNote();
        }
        this.timerID = setTimeout(this.scheduler.bind(this), this.lookahead);
    }

    start() {
        if (!this.isPlaying) {
            this.isPlaying = true;
            this.current16thNote = 0;
            this.nextNoteTime = this.context.currentTime;
            this.scheduler();
        }
    }

    stop() {
        this.isPlaying = false;
        clearTimeout(this.timerID);
    }

    setTempo(newTempo) {
        this.tempo = newTempo;
    }
}
javascript
  • 1 respostas
  • 43 Views
Martin Hope
Ξένη Γήινος
Asked: 2025-04-09 22:19:47 +0800 CST

Como encontrar todos os pontos da grade que correspondem a frações não reduzidas em um quadrado?

  • 13

Dado um inteiro positivo N, podemos rotular todos os pontos da grade no quadrado N x N, começando em 1, o número total de pontos da grade é N x N, e os pontos da grade são list(itertools.product(range(1, N + 1), repeat=2)).

Agora, quero encontrar todas as tuplas (x, y)que satisfazem a condição x/y ser uma fração não reduzida. A seguir, uma implementação de força bruta que é garantidamente correta, mas é muito ineficiente:

import math
from itertools import product


def find_complex_points(lim: int) -> list[tuple[int, int]]:
    return [
        (x, y)
        for x, y in product(range(1, lim + 1), repeat=2)
        if math.gcd(x, y) > 1
    ]

Agora, a próxima função é um pouco mais inteligente, mas gera duplicatas e, como resultado, é apenas visivelmente mais rápida, mas não muito:

def find_complex_points_1(lim: int) -> set[tuple[int, int]]:
    lim += 1
    return {
        (x, y)
        for mult in range(2, lim)
        for x, y in product(range(mult, lim, mult), repeat=2)
    }
In [255]: %timeit find_complex_points(1024)
233 ms ± 4.44 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [256]: %timeit find_complex_points_1(1024)
194 ms ± 1.9 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

Existe uma maneira melhor de fazer isso?

(Meu objetivo é simples, quero criar uma matriz NumPy 2D do tipo uint8 com a forma (N, N), preenchê-la com 255 e tornar todos os pixels (x, y) 0 se (x+1)/(y+1) for uma fração não reduzida)


Eu criei um método que é muito mais inteligente do que os meus dois anteriores, e também tremendamente mais rápido, mas ele ainda gera duplicatas. Optei por não usar setaqui para que você possa copiar e colar o código como está e executar alguns testes e ver a saída exata na ordem em que são gerados:

def find_complex_points_2(lim: int) -> set[tuple[int, int]]:
    stack = dict.fromkeys(range(lim, 1, -1))
    lim += 1
    points = []
    while stack:
        x, _ = stack.popitem()
        points.append((x, x))
        mults = []
        for y in range(x * 2, lim, x):
            stack.pop(y, None)
            mults.append(y)
            points.extend([(x, y), (y, x)])
        
        for i, x in enumerate(mults):
            points.append((x, x))
            for y in mults[i + 1:]:
                points.extend([(x, y), (y, x)])
    
    return points
In [292]: sorted(set(find_complex_points_2(1024))) == find_complex_points(1024)
Out[292]: True

In [293]: %timeit find_complex_points_2(1024)
58.9 ms ± 580 μs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [294]: %timeit find_complex_points(1024)
226 ms ± 3.24 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Para esclarecer, a saída de find_complex_points_2(10)é:

In [287]: find_complex_points_2(10)
Out[287]:
[(2, 2),
 (2, 4),
 (4, 2),
 (2, 6),
 (6, 2),
 (2, 8),
 (8, 2),
 (2, 10),
 (10, 2),
 (4, 4),
 (4, 6),
 (6, 4),
 (4, 8),
 (8, 4),
 (4, 10),
 (10, 4),
 (6, 6),
 (6, 8),
 (8, 6),
 (6, 10),
 (10, 6),
 (8, 8),
 (8, 10),
 (10, 8),
 (10, 10),
 (3, 3),
 (3, 6),
 (6, 3),
 (3, 9),
 (9, 3),
 (6, 6),
 (6, 9),
 (9, 6),
 (9, 9),
 (5, 5),
 (5, 10),
 (10, 5),
 (10, 10),
 (7, 7)]

Como você pode ver, (10, 10)aparece duas vezes. Quero evitar cálculos redundantes.

Isso também acontece em find_complex_points_1, se eu não usar um conjunto, muitas duplicatas serão incluídas, porque o método usado inevitavelmente as gerará repetidamente, ao usar um conjunto ainda há computação desnecessária, ele simplesmente não coleta as duplicatas.

E não, na verdade eu quero que as coordenadas sejam substituídas pela soma de todos os números anteriores, então N é substituído por (N 2 + N) / 2.


Acabei de implementar a geração de imagens para ilustrar melhor o que quero:

import numpy as np
import numba as nb


@nb.njit(cache=True)
def resize_img(img: np.ndarray, h_scale: int, w_scale: int) -> np.ndarray:
    height, width = img.shape
    result = np.empty((height, h_scale, width, w_scale), np.uint8)
    result[...] = img[:, None, :, None]
    return result.reshape((height * h_scale, width * w_scale))


def find_composite_points(lim: int) -> set[tuple[int, int]]:
    stack = dict.fromkeys(range(lim, 1, -1))
    lim += 1
    points = set()
    while stack:
        x, _ = stack.popitem()
        points.add((x, x))
        mults = []
        for y in range(x * 2, lim, x):
            stack.pop(y, None)
            mults.append(y)
            points.update([(x, y), (y, x)])

        for i, x in enumerate(mults):
            points.add((x, x))
            for y in mults[i + 1 :]:
                points.update([(x, y), (y, x)])

    return points


def natural_sum(n: int) -> int:
    return (n + 1) * n // 2


def composite_image(lim: int, scale: int) -> np.ndarray:
    length = natural_sum(lim)
    img = np.full((length, length), 255, dtype=np.uint8)
    for x, y in find_composite_points(lim):
        x1, y1 = natural_sum(x - 1), natural_sum(y - 1)
        img[x1 : x1 + x, y1 : y1 + y] = 0

    return resize_img(img, scale, scale)

composite_image(12, 12)

insira a descrição da imagem aqui

python
  • 4 respostas
  • 240 Views
Martin Hope
Jimbo
Asked: 2025-04-09 22:11:08 +0800 CST

Exceção: As permissões especificadas não são suficientes para chamar SpreadsheetApp.openById

  • 5

Tenho um atalho no iOS que adiciona itens a uma lista de tarefas no Planilhas Google (Code.gs:) e uma macro que organiza minha lista de tarefas bruta sempre que seleciono uma aba de um menu suspenso na coluna D (macro.gs). Cada código funciona quando está em seu próprio arquivo, mas quando está no mesmo arquivo, o Code.gs funciona bem, mas o Macro.gs não funciona e gera este erro:

Exceção: As permissões especificadas não são suficientes para chamar SpreadsheetApp.openById. Permissões necessárias: https://www.googleapis.com/auth/spreadsheets em função desconhecida

Qualquer ajuda é muito apreciada!!

Código.gs:

var financesheet = SpreadsheetApp.openById("IDDDDDD").getSheetByName("Inbox");


function doGet(e) {
  
  var account = JSON.parse(e.parameters.account)
  var detail = JSON.parse(e.parameters.detail)


  var formattedTime = Utilities.formatDate(new Date(), "GMT-4", "h:mm a");
  var formattedDate = Utilities.formatDate(new Date(), "GMT-4", "EEE, MMM d, yyyy");

 financesheet.appendRow([formattedDate,account,detail]);
 
}

Macro.gs:

function onEdit(e) {
  // Log the event to check if the function is triggered
  Logger.log('onEdit Triggered');
  
  // Ensure the edit is made in the "Inbox" sheet
  var sheet = e.source.getSheetByName("Inbox");
  if (!sheet) return;  // Exit if the edit is not in the "Inbox" sheet

  var editedRange = e.range;
  
  // Log details about the edited range to verify which column is being edited
  Logger.log('Edited Range: ' + editedRange.getA1Notation());

  // Check if the edited column is column D (index 4)
  if (editedRange.getColumn() === 4) {
    var valueC = editedRange.getValue();  // Get the value of column D (4th column)
    
    // Log the value of column D to the Execution Log
    Logger.log('Value in Column D (Row ' + editedRange.getRow() + '): ' + valueD);
    
    // Check if column D has a value
    if (valueD != "") {
      var rowValues = sheet.getRange(editedRange.getRow(), 1, 1, 3).getValues()[0];  // Get values from columns A, B, and C
      
      var destinationSheet = e.source.getSheetByName(valueD);
      
      // Append values from columns A, B, and C to the end of the destination sheet
      if (destinationSheet) {
        destinationSheet.appendRow(rowValues);
        
        // Delete the row from the Inbox tab
        sheet.deleteRow(editedRange.getRow());
      }
    }
  }
}
google-sheets
  • 2 respostas
  • 74 Views
Martin Hope
Julie Johnson
Asked: 2025-04-09 21:56:30 +0800 CST

Como analisar corretamente os tempos de execução de chamadas do sistema a partir da saída strace usando pipes em C?

  • 11

Estou trabalhando em uma tarefa de programação de sistema operacional para entender pipes. texto A tarefa envolve o uso de expressões regulares para extrair informações da saída do strace e tempos de execução de chamadas de sistema estatísticos.

No entanto, estou enfrentando problemas com o cálculo incorreto dos tempos. Suspeito que a função parse_strace_line não esteja analisando corretamente as linhas de saída do strace, especialmente a parte do carimbo de data/hora (por exemplo, <0,000123>), resultando em valores de tempo incorretos ou ausentes nas estatísticas. A função pode não estar lidando corretamente com o formato da linha, com casos extremos como linhas incompletas, ou com o padrão regex, que pode não capturar com precisão o componente de tempo da saída do strace.

Meu ambiente é o Ubuntu rodando no WSL2.

Aqui está o código:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <regex.h>

#define MAX_SYSCALLS 1024  // Maximum distinct syscalls we can track
#define TOP_N 5            // Number of top results to display

/* Syscall tracking structure
 * name: syscall name (e.g., "open", "read")
 * time: accumulated time spent in this syscall (seconds)
 */
typedef struct {
    char name[64];
    double time;
} syscall_stat;

/* Main statistics container
 * stats: array of individual syscall metrics
 * count: number of unique syscalls tracked
 * total_time: sum of all syscall times for percentage calculation
 */
typedef struct {
    syscall_stat stats[MAX_SYSCALLS];
    int count;
    double total_time;
} syscall_stats;

/* Parse a line of strace output with timing information (-T option)
 * line: input string from strace output
 * syscall_name: output parameter for extracted syscall name
 * time: output parameter for extracted duration
 * Returns: 1 if successful, 0 if line doesn't contain timing info
 * 
 * Strace line format examples:
 * openat(AT_FDCWD, "/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 <0.000014>
 * read(0, "hello\n", 1024)               = 6 <0.000010>
 */
int parse_strace_line(char* line, char* syscall_name, double* time) {
    // Filter lines without timing information
    if (strstr(line, " = ") == NULL || strstr(line, "<") == NULL) {
        return 0;
    }

    // Regular expression pattern breakdown:
    // ^(\w+)       Capture group 1: syscall name at line start
    // \(.*?\)      Non-greedy match of arguments between parentheses
    // \s+=\s+.*?   Match return value portion
    // <(\d+\.?\d*)> Capture group 2: time value between <>
    regex_t regex;
    regcomp(&regex, "^(\\w+)\\(.*?\\)\\s+=\\s+.*?<(\\d+\\.?\\d*)>$", REG_EXTENDED);
    regmatch_t matches[3];  // Array for regex capture groups

    if (regexec(&regex, line, 3, matches, 0) != 0) {
        regfree(&regex);
        return 0;
    }

    // Extract syscall name from first capture group
    int name_len = matches[1].rm_eo - matches[1].rm_so;
    strncpy(syscall_name, line + matches[1].rm_so, name_len);
    syscall_name[name_len] = '\0';

    // Convert time string to double
    char* time_str = line + matches[2].rm_so;
    *time = atof(time_str);

    regfree(&regex);
    return 1;
}

/* Update statistics with new syscall data
 * stats: pointer to statistics container
 * name: syscall name to add/update
 * time: duration to accumulate
 * 
 * If the syscall already exists, we sum the time.
 * If new, we add it to the list (until MAX_SYSCALLS).
 */
void add_syscall(syscall_stats *stats, const char *name, double time) {
    // Safety check against array overflow
    if (stats->count >= MAX_SYSCALLS) {
        fprintf(stderr, "Warning: Reached maximum tracked syscalls (%d)\n", MAX_SYSCALLS);
        return;
    }

    // Check existing entries for duplicate syscall
    for (int i = 0; i < stats->count; i++) {
        if (strcmp(stats->stats[i].name, name) == 0) {
            stats->stats[i].time += time;
            stats->total_time += time;
            return;
        }
    }

    // Add new entry if space available
    if (stats->count < MAX_SYSCALLS) {
        strncpy(stats->stats[stats->count].name, name, sizeof(stats->stats[0].name));
        stats->stats[stats->count].time = time;
        stats->total_time += time;
        stats->count++;
    }
}

/* Display top N syscalls by accumulated time
 * stats: statistics container with all data
 * n: number of top results to show
 * 
 * Uses bubble sort for simplicity with small datasets.
 * Prints percentages relative to total tracked time.
 * Flushes output with nulls for clean pipe termination.
 */
void print_top_syscalls(syscall_stats *stats, int n) {
    if (stats->count == 0 || stats->total_time == 0) {
        fprintf(stderr, "Error: No valid syscall data to display\n");
        return;
    }

    // Simple O(n²) sort acceptable for MAX_SYSCALLS=1024
    for (int i = 0; i < stats->count - 1; i++) {
        for (int j = i+1; j < stats->count; j++) {
            // Swap if later entry has higher time
            if (stats->stats[j].time > stats->stats[i].time) {
                syscall_stat temp = stats->stats[i];
                stats->stats[i] = stats->stats[j];
                stats->stats[j] = temp;
            }
        }
    }

    // Determine number of results to display
    n = stats->count < n ? stats->count : n;
    for (int i = 0; i < n; i++) {
        double ratio = (stats->stats[i].time / stats->total_time) * 100;
        printf("%s (%d%%)\n", stats->stats[i].name, (int)ratio);
    }

    /* Null-terminate output for clean pipe communication
     * Some programs may read fixed buffer sizes - this ensures
     * we flush the pipe completely and avoid hanging readers */
    for (int i = 0; i < 80; i++) putchar('\0');
    fflush(stdout);
}

/* Main execution flow:
 * 1. Validate command line arguments
 * 2. Set up parent/child process communication
 * 3. Child: execute strace with command
 * 4. Parent: process and analyze strace output
 */
int main(int argc, char *argv[]) {
    if (argc < 2) {
        fprintf(stderr, "Usage: %s COMMAND [ARGS...]\n", argv[0]);
        fprintf(stderr, "Example: %s ls -l\n", argv[0]);
        return 1;
    }

    // Create pipe for inter-process communication
    int pipefd[2];
    if (pipe(pipefd) == -1) {
        perror("Failed to create pipe");
        return 1;
    }

    pid_t pid = fork();
    if (pid == -1) {
        perror("Process fork failed");
        return 1;
    }

    if (pid == 0) { // Child process - execute strace
        // Redirect stdout to pipe write end
        close(pipefd[0]);
        dup2(pipefd[1], STDOUT_FILENO);
        close(pipefd[1]);

        // Build strace argument array:
        // strace -T [user command] [args...]
        char* strace_argv[argc + 2];
        strace_argv[0] = "/usr/bin/strace";
        strace_argv[1] = "-T";  // Enable timing reports
        for (int i = 1; i < argc; i++) {
            strace_argv[i+1] = argv[i];
        }
        strace_argv[argc+1] = NULL;  // NULL-terminate array

        // Execute strace with clean environment
        execve("/usr/bin/strace", strace_argv, (char *[]){ "PATH=/bin:/usr/bin", NULL });
        perror("Failed to execute strace");
        return 1;
    } else { // Parent process - analyze output
        close(pipefd[1]);  // Close unused write end
        syscall_stats stats = {0};  // Initialize all fields to zero

        char buffer[1024];
        char* line_start = buffer;
        ssize_t bytes_read;

        // Read output in chunks until EOF
        while ((bytes_read = read(pipefd[0], 
               line_start, 
               sizeof(buffer) - (line_start - buffer))) > 0) {
            // Null-terminate the received data
            buffer[bytes_read + (line_start - buffer)] = '\0';
            line_start = buffer;

            // Process complete lines (delimited by newlines)
            char* line_end;
            while ((line_end = strchr(line_start, '\n')) != NULL) {
                *line_end = '\0';  // Temporarily terminate at newline

                char syscall_name[64];
                double time;
                if (parse_strace_line(line_start, syscall_name, &time)) {
                    add_syscall(&stats, syscall_name, time);
                }

                line_start = line_end + 1;  // Move to next line
            }

            // Handle partial line remaining in buffer
            if (line_start != buffer) {
                size_t remaining = buffer + sizeof(buffer) - line_start;
                // Move partial line to buffer start for next read
                memmove(buffer, line_start, remaining);
                line_start = buffer + remaining;
            }
        }

        // Cleanup and display results
        close(pipefd[0]);
        wait(NULL);  // Wait for strace to terminate completely
        print_top_syscalls(&stats, TOP_N);
    }

    return 0;
}

Esta é a linha de comando para teste:

root@DimLights:/mnt/f/WSL/Data/OperatingSystems/2025/os2025/sperf# gcc -g -o sperf sperf.c -lm -lrt
root@DimLights:/mnt/f/WSL/Data/OperatingSystems/2025/os2025/sperf# ./sperf echo "Hello WSL"

execve("/bin/echo", ["echo", "Hello WSL"], 0x7ffe6258ee20 /* 1 var */) = 0 <0.000363>
brk(NULL)                               = 0x55d4dee1c000 <0.000104>
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f483b684000 <0.000137>
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory) <0.000115>
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 <0.000133>
fstat(3, {st_mode=S_IFREG|0644, st_size=36191, ...}) = 0 <0.000115>
mmap(NULL, 36191, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f483b67b000 <0.000097>
close(3)                                = 0 <0.000079>
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 <0.000108>
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\220\243\2\0\0\0\0\0"..., 832) = 832 <0.000094>
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784 <0.000101>
fstat(3, {st_mode=S_IFREG|0755, st_size=2125328, ...}) = 0 <0.000096>
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784 <0.000088>
mmap(NULL, 2170256, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f483b469000 <0.000107>
mmap(0x7f483b491000, 1605632, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x28000) = 0x7f483b491000 <0.000117>
mmap(0x7f483b619000, 323584, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b0000) = 0x7f483b619000 <0.000099>
mmap(0x7f483b668000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1fe000) = 0x7f483b668000 <0.000102>
mmap(0x7f483b66e000, 52624, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f483b66e000 <0.000103>
close(3)                                = 0 <0.000104>
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f483b466000 <0.000085>
arch_prctl(ARCH_SET_FS, 0x7f483b466740) = 0 <0.000049>
set_tid_address(0x7f483b466a10)         = 1543 <0.000319>
set_robust_list(0x7f483b466a20, 24)     = 0 <0.000098>
rseq(0x7f483b467060, 0x20, 0, 0x53053053) = 0 <0.000123>
mprotect(0x7f483b668000, 16384, PROT_READ) = 0 <0.000096>
mprotect(0x55d4de99a000, 4096, PROT_READ) = 0 <0.000093>
mprotect(0x7f483b6bc000, 8192, PROT_READ) = 0 <0.000103>
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0 <0.000095>
munmap(0x7f483b67b000, 36191)           = 0 <0.000118>
getrandom("\xc0\x8d\xa3\xbc\x88\x59\xbb\xd3", 8, GRND_NONBLOCK) = 8 <0.000098>
brk(NULL)                               = 0x55d4dee1c000 <0.000113>
brk(0x55d4dee3d000)                     = 0x55d4dee3d000 <0.000097>
fstat(1, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0 <0.000092>
write(1, "Hello WSL\n", 10Received from pipe: Hello WSL
)             = 10 <0.000216>
close(1)                                = 0 <0.000165>
close(2)                                = 0 <0.000092>
exit_group(0)                           = ?
+++ exited with 0 +++
Total count is zero

Aqui está o que eu tentei e o que eu esperava: usei a depuração do GDB e notei que o loop while ((line = strchr(line_start, '\n')) != NULL) foi executado apenas uma vez ao testar o comando. Não consigo entender por que a saída mostra +++ exited with 0 +++ e Total count is zero. Também pedi ajuda à IA e modifiquei partes da função parse_strace_line e o padrão de expressão regular, mas com pouco sucesso.

O que realmente aconteceu: As estatísticas permanecem vazias (a contagem total é zero), indicando que a análise ou extração de dados falhou.

O que eu esperava: O código deveria analisar corretamente os registros de data e hora das chamadas do sistema a partir da saída do strace, acumular seus tempos e calcular a proporção do tempo de cada chamada em relação ao total.

Como estudante, eu agradeceria muito se você pudesse apontar os erros no meu código e explicar como ler corretamente os tempos de chamada do sistema e convertê-los na proporção.

c
  • 1 respostas
  • 97 Views
Prev
Próximo

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve