Pieniä kysymyksiä ohjelmoinnista

woot, käytän juuri Codea en tiennyt tuollaisesta ominaisuudesta. tuli tehtyä nyt apinan hommia mutta jos jatkossa. :thumbsup:
Ottaa aikansa, että editorin ominaisuuksista saa kaiken irti. Kannattaa varmaan tsekata Youtubesta joku VSCode tutoriaali. Noista varmaan ne käytetyimmät ominaisuudet tulee selville nopeasti.
 
Ymmärrän nyt miten tämä toimii, mutta en ymmärrä vielä miten käytän sitä oikein
if __name__ == "__main__":
main()

elikkäs laitetaanko kaikki koodi myös muuttujat ja muut funktiot kaikki tuohon def main(): alle? vai tulisko muuttujat, muutujien alustus, ja muut def funktiot olla ulkopuolella?
def main():

rupesin nyt olemassa olevaan python koodiini lisäämään tätä if toimintoa, mutta rupesin siirtämään kaiken sen alle ja aikamoinen työ vetää joka riville yks tab "4space". Olisiko vain se koodi missä käytetään def funktioita siirrettävä main:in alle?

edit: siirsin nyt kaiken def mainin alle ja koodi ainakin toimii. en tiedä olisiko siinä mitään pahaa jos muuttujat ja def funkkarit olisivat ulkopuolella. ymmärränkö oiken että jos funktiot olisivat ulkopuolella, niitä voisi käyttää ulkopuolelta? nyt kun kaikki on mainin alla niin vain tämä kirjasto saa luvan käyttää funktioita ja koko koodia.
Suositus on käsittääkseni se, että tyypillisesti lähes kaikki halutaan mainin ulkopuolella ja että mainiin jäisi pelkästään se logiikka, jota tarvitaan ohjelman varsinaiseen ajamiseen. Näin ainakin periaatteessa samaa tiedostoa voidaan käyttää sekä kirjastona että sovelluksena. Yksinkertainen esimerkki (paremmankin voisi väsätä, mutta ei ole tähän hätään käytettävissä tähän yhtään enempää aikaa):

Python:
def add(x, y):
    return x + y

def main():
    x = input("Enter a number: ")
    x = float(x)
    
    y = input("Enter another number: ")
    y = float(y)
    print(f"Result: {add(x,y)}")

if __name__ == "__main__":
    main()
Varsinainen kiinnostava logiikka (joka siis oikeasti olisi mitä todennäköisemmin mutkikkaampi kuin tässä add-funktiossa) on nyt add-funktiossa, kun taas mainissa on vain sen verran logiikkaa kuin mitä tarvitaan moduulin ajamiseen jonkinlaisena sovelluksena.
 
Kannattaa myös opetella lukemaan noita kääntäjän/linterin virheilmoituksia ajatuksen kanssa, tuossa ylläolevassa virheilmossa se kerrottiin melko tarkasti, miksi se ei toimi. Tarkoitus siis ei ole vittuilla, itse olin myös aikoinaan laiska noita lukemaan kun opettelin koodaamista ja googlettelin kaiken.
Alkuperäisessä oli loopin ulkopuolella luku1 ja loopissa luku2.
Eli ehkä se luku1 olikin kirjoitusvirhe vaikka piti esitellä luku2 ?

Mutta kuten @Technocrat jo kertoi kannattaa opetella lukemaan virheitä, muuten ei pääse kovin pitkälle...
Joo olette molemmat oikeassa. Vähän väsyneenäkin yritin tuota tehdä niin ei vain mennyt päähän, että mikä siinä rivissä oli virheenä.
 
Miten välitän C#:ssa List<LevelListItem> -objektin React.js:ään? Olen kokeillut JsonConvert.SerializeObject:a ja Json.Serialize:a mutta aina tulee vaan virhe:
"JsRuntimeException: TypeError: Object doesn't support property or method 'map' " Yritän Reactin päässä mapata ne elementteihin.

Samalla systeemillä List<string> meni heittämällä läpi, mutta objekti-lista nyt aiheuttaa ongelmia.

LevelListItem -luokassa on propertyina string ja int.

E: Otin koko Json-enkoodaus väsäyksen pois ja laitoin pelkän listan ilman sitä, niin nyt sivu ei enää kaadu, mutta ei renderöi UI:lle mitään... Eli pitäisikö noi kuitenkin muuntaa johonkin json-tyyppiseen listaan..? Mikähän olisi oikea komento..
 
Viimeksi muokattu:
@Make, näkemättä koodia, koeta rajata se kohta, missä menee vikaan. Mitä siis lähtee sieltä C#:n päästä responsen mukana? Onko se validin näköinen JSON? Jos on, niin sitten katsotaan Reactin päätyä.

Miten teet requestin Reactilla? Axios käytössä? Axios hoitaa konversion object->JSON->object ihan automaattisesti, joten sun ei tarvitse sitä tehdä manuaalisesti. Voitko tulostaa tänne, mitä se Reactin pääty vastaanottaa? Siis ennen kuin yrität mäpätä yhtään mitään.
 
Mulla on raspberryllä C++:lla tehty pieni ohjelma joka toimii websocket serverinä. Frontendinä toimii webbisivu jossa on websocket client, joka muodostaa yhteyden ws://localhost:1234 ja kaikki on hyvin. Mutta jos haluan ottaa yhteyden joltain toiselta koneelta tähän webbisivuun, niin ws://localhost:1234 ei tietenkään toimi kun se yrittää ottaa yhteyden suoraan serveriin joka ei ole enää samalla fyysisellä koneella. Miten toi websocket client pitäis toteuttaa että se frontend ottaa aina yhteyden siihen C++ serveriin siellä laitteen sisällä, riippumatta mistä sitä frontendiä käytetään? Onko esim. websockets/ws tähän tarkoitukseen?
 
Viimeksi muokattu:
Miten toi websocket client pitäis toteuttaa että se frontend ottaa aina yhteyden siihen C++ serveriin siellä laitteen sisällä,

No siis yleisesti sä korvaat sen localhostin sen Raspberryn IP-osoitteella. Jos olette samassa sisäverkossa, niin se voisi esimerkiksi olla "192.168.0.10". Eli koettaisit ottaa yhteyden osoitteeseen ws://192.168.0.10:1234. Sitten pitää olla palomuurit sun muut konffattu päästämään tuo liikenne läpi. Sama periaate jos otat yhteyden internetistä, silloin käytät sen Raspin julkista IP-osoitetta. Mutta silloin pitää ehkä laittaa joku port forwarding päälle reitittimestä, jonka takana se Raspi on. Koska se julkinen osoite pointtaa vain siihen reitittimeen/modeemiin, joka on saanut operaattorilta osoitteen. Se pitää ohjata sisäverkon osoitteeseen.

Ja jos se IP muuttuu, sun pitänee saada sille joku domainnimi joka pointtaa aina oikeaan IP-osoitteeseen.
 
Hmm joo, noin varmaan toimisi myös. Mutta jos haluan että laitteelle on vain portti 80 auki käyttöliittymää varten ja kaikki muu liikenne tapahtuu laitteen sisällä? Ajattelin että pitäis tehdä nodejs websocket server (client?) jota frontend käyttää, joka olis sitten yhteydessä C++ serveriin?
 
Mutta jos haluan että laitteelle on vain portti 80 auki käyttöliittymää varten ja kaikki muu liikenne tapahtuu laitteen sisällä

Se frontti ajetaan selaimessa, ei laitteella. Eli jos frontti tarvitsee porttia 1234 WS:ään, niin sitten se pitää avata, jotta liikenne kulkee. Mutta, WS toimii portin 80 kautta, et tarvitse siihen 1234:ää.
 
Se frontti ajetaan selaimessa, ei laitteella. Eli jos frontti tarvitsee porttia 1234 WS:ään, niin sitten se pitää avata, jotta liikenne kulkee. Mutta, WS toimii portin 80 kautta, et tarvitse siihen 1234:ää.
Onko mun hakema toiminnallisuus siis mahdottomuus? Ei ole mahdollista että kaksi komponenttia keskustelee keskenään vain rasperryn sisällä, ja frontend näyttää vain keskustelun tulokset selaimessa?
 
Onko mun hakema toiminnallisuus siis mahdottomuus? Ei ole mahdollista että kaksi komponenttia keskustelee keskenään vain rasperryn sisällä, ja frontend näyttää vain keskustelun tulokset selaimessa?

Ei tietenkään ole mahdottomuus. Kerrotko, mitä siis tarkalleen haluat tehdä? Vastasin vain siihen, että haluat ottaa WS-yhteyden selaimesta Raspiin portin 1234 kautta. (Ellen siis ymmärtänyt jotain väärin.) WS:ään et tarvitse muuta porttia kuin 80:n.

Mutta mitkä siis on ne 2 komponenttia? Ja oletan, että haluat WS:llä ne tulokset näkymään selaimessa? (Tähän tosiaan riittää vain portti 80/443).
 
Kouluprojektin ja Eclipsen kanssa ongelmia.

Eli teen ohjelmaa, jolla voidaan käsitellä yhtä tietokantaa. Ongelmana on, että Eclipse tulostaa konsoliin koko tietokannan sisällön, vaikka koko ohjelman koodin pyyhkisi pois tai laittaisi kommentteihin. Tein myös kokonaan uuden projektin, jossa ei vielä yhtään koodia ja eikä edes tuota tietokantaa ja se tulostaa silti kaiken siitä. Millä ihmeellä saan tuon takaisin kuntoon? Ei viitsisi poistaakaan koko Eclipseä ja ladata uudestaan, kun työlästä.

EDIT: Nyt korjaantui itsekseen. Loogista, kun tein kokonaan uuden projektin, jossa pikaisesti Hello Worldin ja sekin lähtee tulostamaan koko tietokantaa, jonka poistin.
 
Opiskelen asp.net corea hieman ja teen perinteistä todo appiä mutta kysymys taitaa liittyä enemmänki javascriptiin. Ideoita miten hoitaa juokseva deadline? Viewissä on taskit generoitu foreach loopilla ja loopin sisällä pitäisi kutsua javascript funktiota jolle syötetään taskin deadline. Itse funktio toimii kyllä diviin onclick metodilla mutta miten hoitaa asia että laskuri näkyisi divissä onload?

@foreach(var item in Model.AllTasks){
<div class="col-3 deadline" onclick="timer(@item.deadline)"></div>
}

<script type="text/javascript">
function timer(deadline) {
var deadlineDate = new Date(deadline).getTime();
var x = setInterval(function () {
var now = new Date().getTime();
var distance = deadlineDate - now;
var days = Math.floor(distance / (1000 * 60 * 60 * 24));
var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((distance % (1000 * 60)) / 1000);
$('.deadline').html("Time to deadline: " + days + " Days " + hours + " Hours");
}, 1000)
}
</script>


EDIT: Nyt näyttää toimivan, vaikka jotenkin vaikeeksi tuo tuntui menevän.

$(document).ready(function () {
$(".deadline").each(function () {
$(this).html(timer($(this).data("date"), this));
});
});

ja alkuperäiseen funtioon muoks
function timer(deadline, e) {
//alkuperäiset hutut
var display = days + " Days " + hours + " Hours " + minutes + " Minutes "+ seconds + " Seconds";
$(e).html(display);
}
 
Viimeksi muokattu:
Heip, yritän saada mysli-kantaan raha-arvoja esim:
6945.5040668
2.6528268
Koetan käyttää DESCIMAL muotoa, mutta ei meinaa onnistua.
Eli pääluku voi olla isompikin kuin 4 numeroa, mutta pisteen jälkeen maksimi taitaa olla seitsemän.
Otin jo tyhjän tarkistuksen pois ja huomaan nyt miksi sitä ei kanntata ottaa pois...
Minkäkainen kenttä kannttaisi tuohon laittaa vai mennä ihan varcharilla...

Jos

column_name DECIMAL(P,D);

D:n pitää olla vähemmän tai yhtäsuuri kuin P, niin pitäiskö P täyttää nollilla tai jotain?

Hmm, ilmeisesti ainakin zerofilliä kehiin.
 
Viimeksi muokattu:
column_name DECIMAL(P,D);

D:n pitää olla vähemmän tai yhtäsuuri kuin P, niin pitäiskö P täyttää nollilla tai jotain?

The declaration syntax for a DECIMAL column is DECIMAL(M,D). The ranges of values for the arguments are as follows:

  • M is the maximum number of digits (the precision). It has a range of 1 to 65.
  • D is the number of digits to the right of the decimal point (the scale). It has a range of 0 to 30 and must be no larger than M.


Selvensikö tuo?
 
Selvensikö tuo?
Ei ainakaan vielä.

Kokeilin esimerkiksi että DECIMAL (11,9)
Jolloin data tuotuna
40.76 -> 40.760000000, mutta
534.4 -> 99.999999999
106880 -> 99.999999999 jne

Eli out of rangella mennään. Laitoin unzigened zerofilliksi kentän myös testiksi.
 
Ei ainakaan vielä.

Ok. Eli M on kokonaistarkkuus eli luvun numeroiden KOKONAISmäärä. D on desimaalien määrä. DECIMAL(11,9) tarkoittaa että sulla on yhteensä 11 numeroa, joista 9 on desimaaleja. Eli sen pilkun vasemmalle puolelle jää 11-9 numeroa. Se on 2. Siksi 40.76 toimii mutta 534.4 ei toimi. 534:ssä on 3 numeroa pilkun vasemmalla puolella ja se vaatisi tarkkuudeksi 12, eikä 11 kun desimaaleja on 9.

Sun pitää siis katsoa, että M-D on pilkun vasemmalla puolella tarvittavien numeroiden määrä. Jos haluat jostain ihmeen syystä 9 desimaali ja tallentaa maksimissaan luvun 106880, niin sä tarvitse DECIMAL(15, 9).
 
Tietenkin sitä voisi kokeilla jotain muutakin db:tä (vaikka toki ehkä järkevintä pysyä myslissä kun sen nyt jotenkin tuntee). Esim joku ArnangoDb on ollut vähän kokeilussa. Siitä saisi suoraan microservicejäkin ulos. No, opetellaan tää nyt loppuun ja katsotaan sitten. Serverillä pyörii jo mysli valmiiksi, niin järkevää kai käyttää sitä. Ja kun phpmysal:lla on niin kiva pullautella sisään ja ulos dataa.
 
Ha. Yöllä väsäämisen ihanuus. Olinkin isooon tauluun tehnyt tuon toimivammin eli käyttänyt tarpeeksi isoja rajoja. Aamulla näemmä en muistanut miten olin ratkaissut. Mutta kiitoksia, itseasiassa ymmärrän nyt periaatteen paremmin.
 
Tietenkin sitä voisi kokeilla jotain muutakin db:tä (vaikka toki ehkä järkevintä pysyä myslissä kun sen nyt jotenkin tuntee). Esim joku ArnangoDb on ollut vähän kokeilussa. Siitä saisi suoraan microservicejäkin ulos. No, opetellaan tää nyt loppuun ja katsotaan sitten. Serverillä pyörii jo mysli valmiiksi, niin järkevää kai käyttää sitä. Ja kun phpmysal:lla on niin kiva pullautella sisään ja ulos dataa.

Eipä se kannan vaihto yleensä mitään oikeasti auta, jokaisen tapauksessa joudut kuitenkin opettelemaan miten asiat tehdään juuri siinä kannassa.
Onneksi melkein kaikki sql-kannat ovat hyvin lähellä toisiaan jolloin muiden vastaavien käyttö/vaihto on yleensä helpompaa kuin esimerkiksi vaihto sql->arango tai sql->hbase.
 
Ei ainakaan vielä.

Kokeilin esimerkiksi että DECIMAL (11,9)
Jolloin data tuotuna
40.76 -> 40.760000000, mutta
534.4 -> 99.999999999
106880 -> 99.999999999 jne

Eli out of rangella mennään. Laitoin unzigened zerofilliksi kentän myös testiksi.

Tähän vielä kommentti, unsigned poistaa mahdollisuuden tallentaa negatiivisia lukuja, yleensä rahasummien kanssa se ei ehkä ole tarkoitus ?

Zerofill taas on poistuva määre, se aiheuttaa vain täytön nollilla kentän näyttöpituuteen asti. En muista mistä versiosta mutta tämä pakottaa myös unsigned (koska olisi "väärin" merkitä erim -00000002.25).

Rahasummat pitää aina tyypittää decimal(M,N) riittävän suuriksi ilman lisäjuttuja, silloin summat pysyvät tarkkoina (float/double on siis kielletty koska ne voivat pyöristää lukuja).
Uusissa kannoissa (siis mysql/mariadb) suurin on decimal(65,30), ei pitäisi loppua ihan heti kesken...

Esimerkkinä:
Koodi:
create table t (
  v1 decimal(10,5) unsigned zerofill,
  v2 decimal(10,5)
);

insert into t values (1.75, 1.75);

select * from t;
+-------------+---------+
| v1          | v2      |
+-------------+---------+
| 00001.75000 | 1.75000 |
+-------------+---------+

insert into t values (-1.75, -1.75);
=> ERROR 1264 (22003): Out of range value for column 'v1' at row 1

Eli unsigned/zerofill ei yleensä tee mitään.
 
Mikähän virheilmoitus tämä on visual codessa, kun yritän html tiedostoa avata edge selaimeen. Olen poistanut ja tehnyt uuden launch.jsonin ja sama virhe tulee vaikka laittaa run valikosta start debugging tai run without debugging. Ei auta vaikka tekee kaikki tiedostot workspacesta lähtien uusiksi. Aikaisemmin toimi mainiosti, mutta eilen rupesi tuota virhettä ilmoittamaan.
 

Liitteet

  • Untitled.jpg
    Untitled.jpg
    167,6 KB · Luettu: 53
Mikähän virheilmoitus tämä on visual codessa, kun yritän html tiedostoa avata edge selaimeen. Olen poistanut ja tehnyt uuden launch.jsonin ja sama virhe tulee vaikka laittaa run valikosta start debugging tai run without debugging. Ei auta vaikka tekee kaikki tiedostot workspacesta lähtien uusiksi. Aikaisemmin toimi mainiosti, mutta eilen rupesi tuota virhettä ilmoittamaan.
Itse käytän näitä:
 
Mulla ois lisää tyhmiä kysymyksiä. Eli mulla on funktio joka suostuu console.logaamaan objektin funktion sisällä mutta kun yritän ajaa kyseistä funkkaria toisessa funktiossa se tulostaa undefined. Aavistelisin vian olevan, että async ja sync menee sekasin mutta miten tuon korjaisi, tarvisko jonkun promisen tms?

JavaScript:
function getStationShortCodeForTimeTableQuery (station) {
    const URL = "https://rata.digitraffic.fi/api/v1/metadata/stations/"
    axios(
        {
            method: "GET",
            url: URL,
            headers: {
                "Accept-Encoding": "gzip"
            }
        }
    )
        .then((response) => {
            let body = response.data
            let stationToLowerCase = station.toLowerCase()
                const matchingStation = body.filter(train => train.passengerTraffic === true && train.stationName.toLowerCase().match(stationToLowerCase))
                console.log(matchingStation) // tulostaa objektin sisällön: [{}, {}] (consolen toka loggaus)
                console.log(typeof matchingStation) // == object ( consolen kolmas loggaus)
                return matchingStation
        })

JavaScript:
    let station = req.body.station
        let hmm = getStationShortCodeForTimeTableQuery(station)
        console.log(`${hmm} mikä tää o`) // tulostaa undefined (consolen eka loggaus), typeof = undefined
        res.render("about")
 
console.log ja Promise ovat asynkronisia, kun taas funktiosi on synkroninen. Siksi näet objektin vaikka se ei vielä synkronista koodia suoritettassa ole käytössä.

Eli async/await kehiin ja pitäisi toimia
 
Eli async/await kehiin ja pitäisi toimia

Ja return tuon axios-kutsun eteen. Ja jos tykkää Promise-syntaksista, niin sitten voi laittaa then-kutsun sen getStationShortCodeForTimeTableQuery(station)-kutsun jälkeen, jonka sisällä sitten lokitus ja res.render().
 
console.log ja Promise ovat asynkronisia, kun taas funktiosi on synkroninen. Siksi näet objektin vaikka se ei vielä synkronista koodia suoritettassa ole käytössä.

Eli async/await kehiin ja pitäisi toimia

Menin tutkimaan tuota async await touhua ja saan nyt logattuakin tuossa toisessa funktiossa mutta se ei ole kuitenkaan mitä haen vaan tarvitsen sen palautettavan muuttujaksi että voin lähettää sen templateen renderöitäväksi. Menee yli hilseen ja arvailun puolelle. Onko tarjota rautalankamallia?

JavaScript:
const getStationShortCodeForTimeTableQuery = async (station) => {
    const stationsURL = "https://rata.digitraffic.fi/api/v1/metadata/stations/"
  
    try {
        const resp = await axios({
            method: "GET",
            url: stationsURL,
            headers: {
                "Accept-Encoding": "gzip"
            } 
        })
            if (resp.status == 200) {
                const body = resp.data
                const stationToLowerCase = station.toLowerCase()
                    const matchingStation = body.filter(train => train.passengerTraffic === true && train.stationName.toLowerCase().match(stationToLowerCase))
                    return `${matchingStation[0].stationName}, ${matchingStation[0].stationShortCode}`
            } else {
                console.log("tapahtui virhe")
            }
    } catch (err) {
        console.error(err)
    }
}

JavaScript:
exports.getAllPassengerTrafficStations = (req, res) => {
    let station = req.body.station
        getStationShortCodeForTimeTableQuery(station).then(resp => console.log(resp))
        res.render("about")
}
 
tarvitsen sen palautettavan muuttujaksi että voin lähettää sen templateen renderöitäväksi

Sullahan on jo se muuttujassa, muuttujassa resp tuossa alemmassa koodissa. Eli sen lisäksi että lokitat, sä voit laittaa sinne sen res.render():in. Kun käytät theniä, niin se res.render() pitää olla sen thenin sisällä. Tai sitten laitat asyn/await myös alempaan:

Koodi:
const foo = await getStationShortCodeForTimeTableQuery();
res.render(foo); // Tai mitä nyt haluatkin tehdä

Käyttäisin samaa tapaa joka paikassa eli joko .then() tai sitten async/await. En ehkä sekaisin. Ja jos teet async/await, niin se exports.getAllPassengerTrafficStations pitää määritellä asyn:ksi.
 
Sullahan on jo se muuttujassa, muuttujassa resp tuossa alemmassa koodissa. Eli sen lisäksi että lokitat, sä voit laittaa sinne sen res.render():in. Kun käytät theniä, niin se res.render() pitää olla sen thenin sisällä. Tai sitten laitat asyn/await myös alempaan:

Koodi:
const foo = await getStationShortCodeForTimeTableQuery();
res.render(foo); // Tai mitä nyt haluatkin tehdä

Käyttäisin samaa tapaa joka paikassa eli joko .then() tai sitten async/await. En ehkä sekaisin. Ja jos teet async/await, niin se exports.getAllPassengerTrafficStations pitää määritellä asyn:ksi.

Voi perkele luulin yrittäneeni just tuolla then:issä renderöidä jo kertaalleen, mutta ehkäpä meni placeholder ja muuttuja sekasin tai jotain muuta jännää.

Kiitoksia, ehkä tämä on nyt jotenkin sisäistetty.
 
Tarkoituksena lukea osoitteesta http://www.peto-media.fi/tiedotteet/rss.xml löytyvää rss syötettä. Ongelmana on, että ääkköset näkyvät � muodossa.
Liittynee merkistön enkoodaukseen. Ymmärtääkseni tuo pelastuslaitoksen rss syöte on enkoodattuna ISO-8859-1 merkistöön.

Mitä taikoja tässä täytyy tehdä, että tuo saadaan tuollaisenaan myös ulos?

Varmaan jäi jotain muutakin olennaista kertomatta, mutta kyseessä Node.js räpellys.
 
Mistään mitään tietämättä ongelmasi viittaisi siihen että sinulta puuttuu jostain maaginen komento

{'Content-Type': 'text-html; charset=utf-8'}
 
Pitääpä itsekin pitkästä aikaa kysyä täältä viisaampien apua kun javascriptiä en oikein ole noin 15 vuoteen koodannut ja jquery on vielä vieraampaa. Olen siis koodailemassa omaa kotiautomaatio/kodinohjausjärjestelmääni uusiksi. Kooditagien sisällä on mahdollisimman simppeli ongelmallinen koodinpätkä, oikean html:n generoi minulla python-skripti automaattisesti ja siinä on aika paljon kaikkea muutakin. Nykyinen koodi sinällään kuitenkin toimii.
HTML:
<html><head>
<script src="jquery-3.5.1.min.js"></script>
<script>
$(document).ready(function(){
  $.get("ajaxtest.py?id=1", function(result){ $( "#a1" ).html( "<small>" + result + "</small>" ); });
  $.get("ajaxtest.py?id=2", function(result){ $( "#a2" ).html( "<small>" + result + "</small>" ); });
  $.get("ajaxtest.py?id=13", function(result){ $( "#a13" ).html( "<small>" + result + "</small>" ); });
  $.get("ajaxtest.py?id=63", function(result){ $( "#a63" ).html( "<small>" + result + "</small>" ); });
  $.get("ajaxtest.py?id=88", function(result){ $( "#a88" ).html( "<small>" + result + "</small>" ); });
});
</script>
</head>
<body>
    <table>
        <tr><td>Test</td><td id="a1">asd</td></tr>
        <tr><td>Test</td><td id="a2">asd</td></tr>
        <tr><td>Test</td><td id="a13">asd</td></tr>
        <tr><td>Test</td><td id="a63">asd</td></tr>
        <tr><td>Test</td><td id="a88">asd</td></tr>
    </table>
</body></html>
Ajattelin, että nuo $.get() -rivit varmaankin saisi jotenkin tehtyä jollain luupilla ettei tarvitsisi tehdä/generoida jokaiselle ladattavalle id:lle omaa riviä. Noita rivejä tulee lopputuloksessa olemaan noin viitisenkymmentä kappaletta ja id-numerot saattavat olla mitä tahansa arviolta 1 ja 500 väliltä. Tuo html-taulukko siis generoituu tosiaan automaattisesti tekemälläni python-skriptillä joten tarvittaessa saan sitäkin muutettua.

Noiden ajaxtest.py suorittaminen kestää noin sekunnista kymmeneen sekuntiin kappaleelta riippuen id:stä jonka takia ajattelin latailla ne jqueryllä. Aluksi tosin ajattelin että tuo skripti joka luo tuon html:n olisi suoraan käynyt hakemassa nuo toisen skriptin hakemat tiedot mutta sivun latautuminen kesti aivan liian kauan eikä noiden tietojen ilmestyminen viiveellä haittaa mitään.
 
Pitääpä itsekin pitkästä aikaa kysyä täältä viisaampien apua kun javascriptiä en oikein ole noin 15 vuoteen koodannut ja jquery on vielä vieraampaa. Olen siis koodailemassa omaa kotiautomaatio/kodinohjausjärjestelmääni uusiksi. Kooditagien sisällä on mahdollisimman simppeli ongelmallinen koodinpätkä, oikean html:n generoi minulla python-skripti automaattisesti ja siinä on aika paljon kaikkea muutakin. Nykyinen koodi sinällään kuitenkin toimii.
HTML:
<html><head>
<script src="jquery-3.5.1.min.js"></script>
<script>
$(document).ready(function(){
  $.get("ajaxtest.py?id=1", function(result){ $( "#a1" ).html( "<small>" + result + "</small>" ); });
  $.get("ajaxtest.py?id=2", function(result){ $( "#a2" ).html( "<small>" + result + "</small>" ); });
  $.get("ajaxtest.py?id=13", function(result){ $( "#a13" ).html( "<small>" + result + "</small>" ); });
  $.get("ajaxtest.py?id=63", function(result){ $( "#a63" ).html( "<small>" + result + "</small>" ); });
  $.get("ajaxtest.py?id=88", function(result){ $( "#a88" ).html( "<small>" + result + "</small>" ); });
});
</script>
</head>
<body>
    <table>
        <tr><td>Test</td><td id="a1">asd</td></tr>
        <tr><td>Test</td><td id="a2">asd</td></tr>
        <tr><td>Test</td><td id="a13">asd</td></tr>
        <tr><td>Test</td><td id="a63">asd</td></tr>
        <tr><td>Test</td><td id="a88">asd</td></tr>
    </table>
</body></html>
Ajattelin, että nuo $.get() -rivit varmaankin saisi jotenkin tehtyä jollain luupilla ettei tarvitsisi tehdä/generoida jokaiselle ladattavalle id:lle omaa riviä. Noita rivejä tulee lopputuloksessa olemaan noin viitisenkymmentä kappaletta ja id-numerot saattavat olla mitä tahansa arviolta 1 ja 500 väliltä. Tuo html-taulukko siis generoituu tosiaan automaattisesti tekemälläni python-skriptillä joten tarvittaessa saan sitäkin muutettua.

Noiden ajaxtest.py suorittaminen kestää noin sekunnista kymmeneen sekuntiin kappaleelta riippuen id:stä jonka takia ajattelin latailla ne jqueryllä. Aluksi tosin ajattelin että tuo skripti joka luo tuon html:n olisi suoraan käynyt hakemassa nuo toisen skriptin hakemat tiedot mutta sivun latautuminen kesti aivan liian kauan eikä noiden tietojen ilmestyminen viiveellä haittaa mitään.

Yksinkertaisin on varmaan tehdä id- numeroista taulukko ja loopata se läpi siellä missä tarvitaan, eli ready():n getit (ja ehkä taulukon rivit myös)
 
Itse ratkoisin tämän Promise.all:illa, eli jokainen fetch taulukkoon, joka sitten ajetaan ja homman ollessa ohi luupataan läpi ja tuodaan sivulle: Promise.all Example (toimiva koodiesimerkki)

Koodi voi olla hieman hankalasti ymmärrettävää, jos JavaScriptin "tuijottamisesta" on jo vierähtänyt aikaa. Mutta kysy rohkeasti, niin selitetään täällä, mistä on kyse.
 
Joo-o... Pitää huomenna tuijotella tuota esimerkkiä vähän lisää, nyt ei enää oikein tähän aikaan järki luista tarpeeksi. Ainakin nopealla vilkaisulla tuo koodi sinänsä näytti sellaiselta että hetken perehtymisellä otan siitä jotain tolkkua. Tuollaisenaan ilmeisesti joko oma tähänastinen html:ää generoiva python-skripti tai tuo esimerkin javascript vaatii kohtalaisesti puukkoa että saa aikaiseksi sitä mitä ajattelin.

Tuota ississ:in ideaa itsekin koitin huonolla menestyksellä rakennella, jotenkin vaan en mitenkään saanut noita html:n joukossa olevia id:itä luettua taulukkoon. Sen jälkeenhän se ei enää olisi muuta kuin käydä taulukko läpi ja sijoittaa id:n numero kahteen kohtaan tuota get-riviä.
 
@Hyrava tsekkaa js-funktiot document.querySelector ja document.querySelectorAll. Näiden avulla saat arrayn itemeistä:
document.querySelectorAll("tr")
.forEach(item => console.log(item.children[1].id))
Promise.all ei auta "...saisi jotenkin tehtyä jollain luupilla ettei tarvitsisi tehdä/generoida jokaiselle ladattavalle id:lle omaa riviä..." ongelmaan. Sillä saat tosin kaikki rivit päivittymään samaan aikaan (eli kun viimeinenkin kutsu on resolvattu) jos sitä haet. Ilman promisea taulukon itemit päivittyvät heti, kun kyseisen rivin kutsu on resolvattu.
 
Viimeksi muokattu:
En oikein ymmärrä hyravan juttua, mutta eikö pythonilla voi tehdä koko html sivua, django template? Toinen on että tallettaa idt esim .json tiedostoon pythonilla ja lukee javascriptillä. Mistä ne idt tulee ja kuinka usein ne muuttuu?
 
@Samppa
Tuohan vaikuttaisi ehkäpä toimivalta ongelmaani, pitää töiden jälkeen kokeilla. Olin siis vähän jäljillä omissa kokeiluissani mutta en keksinyt tuota document.querySelector -juttua. Eilen kun rupesin illalla käymään ilmaista javascript-nettikurssia muistin virkistämiseksi, tuli todettua että aika paljon vettä on virrannut siitä kun viimeksi js:ään koskenut...

@Letuk
Juu, siis tämä mun projekti tosiaan on ehkä vähän poikkeuksellinen eli ei mikää tavanomainen nettisivu vaan omassa kotiverkossa toimivan itse tehdyn automaatio/ohjausjärjestelmän käyttöliittymä.

Toki voisin pythonilla luoda koko sivun jokaisella sivulatauksella jolloin sivun latautumiseen kestäisi ikuisuus. Toinen vaihtoehto olisi tietty muutaman minuutin välein generoida nuo tiedot valmiiksi johonkin tiedostoon tai tietokantaan mutta en näe sitä järkevänä koska tuolla sivulla ei vierailla normaalitilanteessa kovin usein joten ihan turhaan varmuuden vuoksi noita generoitaisiin. Sitten taas yli muutaman minuutin ikäiset arvot ovat vanhentuneita joten ne joka tapauksessa olisi kiva hakea tuoreeltaan.

Nuo id:t siis saattavat vaihtua jokaisella sivulatauksella tai sitten ovat samoja vaikkapa kuukauden ajan, riippuen mitä noille ohjausjärjestelmän laitteille kuuluu. Niiden id:iden takaa löytyvät arvot taas vaihtuvat varsin tiuhaan.

Vanha systeemi on jo sellainen silisalaatti html, css, javascript, php5, python2, python3, c, c++, perl ja shelliskriptejä ja tuon kaaoksen ylläpito alkaa olla jo sellainen helvetti että rupesin uusimaan tuota vähän vähemmillä teknologioilla.
 
Noniin, pääsin tuolla @Samppa vinkillä jo niin pitkälle että sain id:t napattua ja niiden perusteella luupattua $.get():llä nuo läpi mutta jostain syystä kaikki arvot päivittyvät peräkkäin viimeisen id:n sijaintiin. Eli allaolevalla koodinpätkällä toimii jo lähestulkoon oikein, html on sama kuin aiemmin. console.log():lla kyllä katselin että kaikki id:t käydään järjestyksessä läpi. Luultavasti tässä taas on joku hyvin simppeli aivopieru mitä en keksi.
HTML:
<script>
$(document).ready(function(){

document.querySelectorAll("tr").forEach(getdata);

function getdata(item) {
    solu = "#"+item.children[1].id;
    nro = item.children[1].id.substring(1);
    $.get("ajaxtest.py?id="+nro, function(result){ $( solu ).html( "<small>" + result + "</small>" ); });
}

});
</script>
 
Noniin, pääsin tuolla @Samppa vinkillä jo niin pitkälle että sain id:t napattua ja niiden perusteella luupattua $.get():llä nuo läpi mutta jostain syystä kaikki arvot päivittyvät peräkkäin viimeisen id:n sijaintiin. Eli allaolevalla koodinpätkällä toimii jo lähestulkoon oikein, html on sama kuin aiemmin. console.log():lla kyllä katselin että kaikki id:t käydään järjestyksessä läpi. Luultavasti tässä taas on joku hyvin simppeli aivopieru mitä en keksi.
HTML:
<script>
$(document).ready(function(){

document.querySelectorAll("tr").forEach(getdata);

function getdata(item) {
    solu = "#"+item.children[1].id;
    nro = item.children[1].id.substring(1);
    $.get("ajaxtest.py?id="+nro, function(result){ $( solu ).html( "<small>" + result + "</small>" ); });
}

});
</script>
Koodi:
    solu = "#"+item.children[1].id;
Tässä luodaan globaali muuttuja.
Koodi:
    function(result){ $( solu ).html( "<small>" + result + "</small>" );
Täällä puolestaan käytetään globaalia muuttujaa (jonka arvo suoritushetkellä on todennäköisesti silmukassa viimeiseksi saatu arvo).

jQueryä paremmin tuntematta en mene neuvomaan miten tämä korjataan, mutta tuossa on pohjimmainen ongelma.
 
Joo, toihan se on. Eli ”const” eteen. Jqueryä et myöskään tarvitsisi, nykyään js:ssä on natiivina fetch-api
 
Toki voisin pythonilla luoda koko sivun jokaisella sivulatauksella jolloin sivun latautumiseen kestäisi ikuisuus. Toinen vaihtoehto olisi tietty muutaman minuutin välein generoida nuo tiedot valmiiksi johonkin tiedostoon tai tietokantaan mutta en näe sitä järkevänä koska tuolla sivulla ei vierailla normaalitilanteessa kovin usein joten ihan turhaan varmuuden vuoksi noita generoitaisiin. Sitten taas yli muutaman minuutin ikäiset arvot ovat vanhentuneita joten ne joka tapauksessa olisi kiva hakea tuoreeltaan.
Mutta jos se sivun luova python hakisikin taulukkoon sisällön asynkronisesti (multiprocessing, threading), ja päivittäisi serverillä olevaa sivua sitä mukaa kuin tietoja saadaan, ja lopettaisi päivityksen kunhan kaikki tiedot on kertaalleen kerätty tai kun aikaa on kulunut sopivasti, niin asiakaspäässä riittäisi pelkkä http-refresh sopivin välein. Sekä nappi, jolla saa päivityksen taas käyntiin. jQuery on tässä tarpeeton, ja sen sivun saa tehtyä myös ilman javascriptiä.
 
Juu, heti kun luin tuon sanan "globaali", tajusin itsekin tuon ongelman. Ja toisaan kun en ole 15 vuoteen javascriptiä koodannut niin nyt kun on taas vähän palautellut sitä mieleen ja opetellut, on tullut huomattua että nykyisellä javascriptillä ja sillä javascriptillä mitä tuli aikanaan tehtyä on eroa kuin yöllä ja päivällä. On tullut kaikenlaisia "fat arrow" -juttuja sun muita ihan älyttömästi lisää. Kiitoksia vaan neuvoista, nyt näyttäisi toimivan halutusti ja pääsee liimaamaan tuon siihen suurempaan kokonaisuuteen.

hrk, varmaan tuon voisi tehdä noinkin, mutta koitan tehdä tätä mahdollisimman pitkälti niillä taidoilla mitä mulla on. Kuitenkin vaikka suuri osa on ihan tuttua niin aina välillä tulee tällaisia pikkujuttuja joita ensin yritän omin voimin ratkoa ja lopulta joudun kyselemään esim täällä. Esim nuo multiprocessing ja threading ovat vielä lähestulkoon tuntemattomia asioita ja kun tätä tekee vapaa-ajalla ihan harrastuspohjalta niin ei ole oikein resursseja opetella ihan kaikkea vaikka mieli tekisikin. Ehkä sitten seuraavassa versiossa käytän noitakin. Tämäkin on jo parannus kun saa edes suurimman osan vanhoista purkkavirityksistä siivoiltua.
 
hrk, varmaan tuon voisi tehdä noinkin, mutta koitan tehdä tätä mahdollisimman pitkälti niillä taidoilla mitä mulla on. Kuitenkin vaikka suuri osa on ihan tuttua niin aina välillä tulee tällaisia pikkujuttuja joita ensin yritän omin voimin ratkoa ja lopulta joudun kyselemään esim täällä. Esim nuo multiprocessing ja threading ovat vielä lähestulkoon tuntemattomia asioita ja kun tätä tekee vapaa-ajalla ihan harrastuspohjalta niin ei ole oikein resursseja opetella ihan kaikkea vaikka mieli tekisikin. Ehkä sitten seuraavassa versiossa käytän noitakin. Tämäkin on jo parannus kun saa edes suurimman osan vanhoista purkkavirityksistä siivoiltua.
Näinhän se on. Mutta kun ymmärsin että vaihtoehdotkin kiinnostavat, ja kun minulla tuota aikaa on, niin näpersin pienen python-skriptin, joka lukee muutaman kuvitteellisen "anturin", joiden lukemiseen kuluu max 10 sekuntia / anturi, ja tekee tämän multiprocessing-rinnakkaistetusti niin, että kokonaisaika riippuu periaatteessa vain hitaimmasta anturista, jos prosessien määrää ei rajoiteta. Eli siis skriptin ajoaika on 10 sekuntia + overhead, vaikka antureita olisi sata. Lopuksi skripti rakentaa tuloksista html-raportin ja avaa sen oletusselaimessa. Mikään webiserverin kautta jaettava sovellus tämä ei kuitenkaan ole.
Koodi:
import multiprocessing as mp
import os, time, random
import tempfile

# anturien tunnukset
id = ['lämpö, ulko', 'lämpö, olkkari', 'lämpö, makkari',
    'lämpö, sauna', 'oluita, jääkaapissa', 'meilejä, lukematta']

def test(id):
    viive = random.randint(1, 10)
    time.sleep(viive)
    return random.randint(1,30)
   
def f(Q, idx):
    Q.put((idx, test(id[idx])))

def startjobs(Q, count):
    for i in range(count):
        p = mp.Process(target=f, args=(Q, i))
        p.start()
        # fire and forget: no join

def main():
    Q = mp.Queue()
    count = len(id)
    t = time.time()
    startjobs(Q, count)
    results = []
    while(count):
        idx, value = Q.get()
        results.append((id[idx], value))
        count -= 1
    page = "<html><body>\n<table>\n"
    page += "<tr><th style=\"text-align:left;\">Anturi</th><th>Lukema</th></tr>"
    for result in sorted(results):
        ident, value = result
        page += f"\n<tr><td>{ident}</td><td>{value}</td></tr>"
    page += "\n</table>\n</body></html>"
    with tempfile.NamedTemporaryFile('w',suffix=".html", delete=False) as f:
        f.write(page)
        tempname = f.name
    os.startfile(tempname)
    time.sleep(1)   # give time for browser to open file
    os.remove(tempname)

if __name__ == "__main__":
    # main process only
    main()
 
Viimeksi muokattu:
Hmm... eihän tuo nyt niin kovin monimutkaiselta ainakaan yhtäkkiä vaikuta. Ainakin luulen ymmärtäväni kuinka tuo toimii ihan näin nopealla vilkaisullakin. Pitääpä ottaa tuo skriptinpätkä talteen ja tutustua siihen joskus paremmalla ajalla. Kiitoksia tuostakin, ei sitä tiedä jos vaikka joskus jotain tuontyyppistäkin tekisi johonkin projektiin.
 
Hmm... eihän tuo nyt niin kovin monimutkaiselta ainakaan yhtäkkiä vaikuta. Ainakin luulen ymmärtäväni kuinka tuo toimii ihan näin nopealla vilkaisullakin. Pitääpä ottaa tuo skriptinpätkä talteen ja tutustua siihen joskus paremmalla ajalla. Kiitoksia tuostakin, ei sitä tiedä jos vaikka joskus jotain tuontyyppistäkin tekisi johonkin projektiin.
Joo, Pythonin multiprocessing-kirjasto on mukava, kun jokaisella prosessilla on oma kopio kaikesta ja voidaan tehdä mitä vaan. Threading-kirjasto on paljon krantumpi. Mutta kyllä tämä nyt puheena oleva tehtävä hoituu paremmin siten kuin olet sen hoitanut. Kun se webiserveri joka tapauksessa on. AJAX on hieno keksintö.
 
Auttakaahan tumpeloa mäessä, laitoin virtuaalikoneen mittaamaan uuden kuituyhteyden nopeutta sen vaihtuvuuden takia. Ohjeet otin täältä: Raspberry Pi Internet Speed Monitor

Koodinpätkällä:

Koodi:
import re
import subprocess
from influxdb import InfluxDBClient

response = subprocess.Popen('/usr/local/bin/speedtest-cli --simple', shell=True, stdout=subprocess.PIPE).stdout.read().decode('utf-8')
ping = re.findall('Ping:\s(.*?)\s', response, re.MULTILINE)
download = re.findall('Download:\s(.*?)\s', response, re.MULTILINE)
upload = re.findall('Upload:\s(.*?)\s', response, re.MULTILINE)

ping = ping[0].replace(',', '.')
download = download[0].replace(',', '.')
upload = upload[0].replace(',', '.')

speed_data = [
    {
        "measurement" : "internet_speed",
        "tags" : {
            "host": "RaspberryPiMyLifeUp"
        },
        "fields" : {
            "download": float(download),
            "upload": float(upload),
            "ping": float(ping)
        }
    }
]
client = InfluxDBClient('localhost', 8086, 'speedmonitor', 'pimylifeup', 'internetspeed')

client.write_points(speed_data)

saan Influxin kautta ulos Grafanaan grafiikkaa. Mutta tuo käytettävä speedtest-cli on ilmeisesti huonosti toimiva. Löysin Githubista paremmin toimivan: taganaka/SpeedTest

Tuo kumminkin tulostaa erimuotoista dataa pihalle:

speedtest-cli --simple

Koodi:
Ping: 5.424 ms
Download: 404.41 Mbit/s
Upload: 663.63 Mbit/s

SpeedTest --output text

Koodi:
IP=****
IP_LAT=***
IP_LON=***
PROVIDER=Keski-Suomen Valokuituverkot Oy
TEST_SERVER_HOST=nopeustesti2.ksvvnet.fi:8080
TEST_SERVER_DISTANCE=85.1755
LATENCY=3
JITTER=0
DOWNLOAD_SPEED=713.05
UPLOAD_SPEED=1047.20

Millä re.findall-parametreilla saan tuosta toisesta haettua vastaavat tiedot Ping, Download ja Upload kenttiin? Eli pelkkä numeraalinen arvo pitäisi hakea.
 
Viimeksi muokattu:
Millä re.findall-parametreilla saan tuosta toisesta haettua vastaavat tiedot Ping, Download ja Upload kenttiin? Eli pelkkä numeraalinen arvo pitäisi hakea.

Python:
ping = re.findall('LATENCY=(.*?)\s', response, re.MULTILINE)
download = re.findall('DOWNLOAD_SPEED\=(.*?)\s', response, re.MULTILINE)
upload = re.findall('UPLOAD_SPEED\=(.*?)$', response, re.MULTILINE)

Huom. Tuo uploadin pattern olettaa sitten että tuo stringi päättyy tuon upload-osion jälkeen, eli jos se vielä jatkuukin niin tuo ei toimi, vaan tarvii pienen muokkauksen tuohon. Eipäs oletakaan MULTILINE-flagin kanssa.

EDIT: Hups, jäi tuo muuttujan nimi vääräksi tuonne findall-komentoon, nyt korjattu niin että pitäisi toimia suoraan.
 
Viimeksi muokattu:
Python:
ping = re.findall('LATENCY=(.*?)\s', response, re.MULTILINE)
download = re.findall('DOWNLOAD_SPEED\=(.*?)\s', response, re.MULTILINE)
upload = re.findall('UPLOAD_SPEED\=(.*?)$', response, re.MULTILINE)

Huom. Tuo uploadin pattern olettaa sitten että tuo stringi päättyy tuon upload-osion jälkeen, eli jos se vielä jatkuukin niin tuo ei toimi, vaan tarvii pienen muokkauksen tuohon.

EDIT: Hups, jäi tuo muuttujan nimi vääräksi tuonne findall-komentoon, nyt korjattu niin että pitäisi toimia suoraan.
Eikös tuo MULTILINE-optio ole juurikin tuo "pieni muokkaus". Silloin siis dollarimerkki matchaa sekä rivinvaihdot että stringin lopun. Eli nuo pingin ja downloadin \s-merkit voisi myös korvata $:lla, jolloin kaikki toimii riippumatta siitä missä järjestyksessä rivit on listattu.
 
Eikös tuo MULTILINE-optio ole juurikin tuo "pieni muokkaus". Silloin siis dollarimerkki matchaa sekä rivinvaihdot että stringin lopun. Eli nuo pingin ja downloadin \s-merkit voisi myös korvata $:lla, jolloin kaikki toimii riippumatta siitä missä järjestyksessä rivit on listattu.

Erinomainen huomio, pitää paikkaansa. Nopeasti nakuttelin vaan sopivat patternit ja testasin, enkä miettinyt tuota MULTILINE-flagia sen enempää. :)
 

Statistiikka

Viestiketjut
253 991
Viestejä
4 418 023
Jäsenet
73 259
Uusin jäsen
Duane

Hinta.fi

Back
Ylös Bottom