Pieniä kysymyksiä ohjelmoinnista

Liittynyt
28.02.2021
Viestejä
40
Minun pitää lukea tiedostosta nuo rivit ja muuttaa ne eri muotoon, mitkä kirjoitetaan toiseen tiedostoon. Eli tästä tulee ohjelma mikä muuttaa konfiguration toiseen laitevalmistajan muotoon. Olisin pistänyt tähän mallikonfiguraation, mutta ei ollut yhtään tallessa.

Eli:

---- TÄMÄ TEKSTI ON KONFIGURAATION KESKELLÄ, ELI TEKSTIÄ ON YLÄ-/ ALAPUOLELLA (GLOBAALIT KOMENNOT YMS) ----

vlan 100
untagged 1,2
tagged 25

---------------------------------------------------------------------------------------------------------------------------------------

Poimitaan edellisestä konfiguraatiosta tiedot ja muutetaan alla olevaan muotoon. Tämä kirjoitetaan uuteen tiedostoon, josta tulee toisen laitevalmistajan konfiguraatio:

interface Gigabitethernet1/0/1
switchport mode access
switchport acces vlan 100

interface Gigabitethernet1/0/2
switchport mode access
switchport acces vlan 100

interface Gigabitethernet1/0/25
switchport mode trunk
switchport trunk allowed vlan 100
Itse olen töissä tehnyt vastaavia harjoitteita hyödyntäen tätä CiscoConfParse -kirjastoa, joka nimestään huolimatta taipuu moneen.
 
Liittynyt
18.10.2016
Viestejä
476
Miten python pitäisi rakentaa, jos haluan syöttää uusia parametrejä while-loopissa / sleep-odotuksessa? Eli tuossa while-aikana olisi mahdollista syöttää uusi odotusaika tai 'pause' komento mikä jäädyttää loopin, tai 'exit' mikä lopettaa sen.

Pääohjelmani muodostuu esimerkin mukaisesti, ja while-looppi intervalli n. 5min. Jos on myös ehdotus millä saan absoluuttisen tarkasti tuon toteutumaan 5min välein, niin senkin voisin ottaa vastaan, vaikka ihan mielenkiinnosta miten se tehtäisiin.

Koodi:
from datetime import datetime

def main():
    transfer_interval = 300
    while(True):
        startinseconds = datetime.now().timestamp()
        
        #...
        #datan siirtoa netin yli, taulukoiden yhdistämistä, kestää ~10sec normaalisti
        #koodirivejä ~60
        #...
        
        sleep_time = transfer_interval-(datetime.now().timestamp() - startinseconds)
        time.sleep(sleep_time)
 

hrk

Liittynyt
23.07.2017
Viestejä
1 730
Miten python pitäisi rakentaa, jos haluan syöttää uusia parametrejä while-loopissa / sleep-odotuksessa? Eli tuossa while-aikana olisi mahdollista syöttää uusi odotusaika tai 'pause' komento mikä jäädyttää loopin, tai 'exit' mikä lopettaa sen.

Pääohjelmani muodostuu esimerkin mukaisesti, ja while-looppi intervalli n. 5min. Jos on myös ehdotus millä saan absoluuttisen tarkasti tuon toteutumaan 5min välein, niin senkin voisin ottaa vastaan, vaikka ihan mielenkiinnosta miten se tehtäisiin.

Koodi:
from datetime import datetime

def main():
    transfer_interval = 300
    while(True):
        startinseconds = datetime.now().timestamp()
     
        #...
        #datan siirtoa netin yli, taulukoiden yhdistämistä, kestää ~10sec normaalisti
        #koodirivejä ~60
        #...
     
        sleep_time = transfer_interval-(datetime.now().timestamp() - startinseconds)
        time.sleep(sleep_time)
Tehtävän ratkaisussa joutuu tutustumaan joko säikeisiin tai tapahtumalooppiin. Pelkkä time.sleep() on liian simppeli, torkkujen aikana ohjelma ei tee mitään.

Säikeiden käyttöön liittyy paljon kikkoja ja rajoituksia. Pythonissa on kuitenkin vakiona tkinter-framework, joka varsinaisesti on tarkoitettu graafisen käyttöliittymän tekemiseen. Sen ytimenä olevaa tapahtumalooppia voi tässäkin hyödyntää:

Python:
import tkinter as tk

root = tk.Tk()
root.title("tämä on vain hassu esimerkki")

seconds = 10
running = False

def task():
    # tämä on toistettava tehtävä
    print("Täällä taas: intervalli nyt", seconds)
    root.after(1000 * seconds, task)

def start():
    global running, seconds
    # tässä konfiguroidaan
    s = input("Intervalli sekunteina? ")
    if s.isdecimal(): seconds = int(s)
    if not running:
        running = True
        task()

button = tk.Button(root, text="Toistuvaistyön\nkäynnistys",
    font="Calibri 24 bold", command=start)
button.pack(padx=100, pady=100)
tk.mainloop()
 
Viimeksi muokattu:

hrk

Liittynyt
23.07.2017
Viestejä
1 730
Tehtävän ratkaisussa joutuu tutustumaan joko säikeisiin tai tapahtumalooppiin. Pelkkä time.sleep() on liian simppeli, torkkujen aikana ohjelma ei tee mitään.

Säikeiden käyttöön liittyy paljon kikkoja ja rajoituksia. Pythonissa on kuitenkin vakiona tkinter-framework, joka varsinaisesti on tarkoitettu graafisen käyttöliittymän tekemiseen. Sen ytimenä olevaa tapahtumalooppia voi tässäkin hyödyntää:

Python:
import tkinter as tk

root = tk.Tk()
root.title("tämä on vain hassu esimerkki")

seconds = 10
running = False

def task():
    # tämä on toistettava tehtävä
    print("Täällä taas: intervalli nyt", seconds)
    root.after(1000 * seconds, task)

def start():
    global running, seconds
    # tässä konfiguroidaan
    s = input("Intervalli sekunteina? ")
    if s.isdecimal(): seconds = int(s)
    if not running:
        running = True
        task()

button = tk.Button(root, text="Toistuvaistyön\nkäynnistys",
    font="Calibri 24 bold", command=start)
button.pack(padx=100, pady=100)
tk.mainloop()
Yksinkertaisesta esimerkistä tulee vielä yksinkertaisempi käytettäessä tkinterin sijasta threading-kirjastoa.
Tulostus tosin menee tässä sotkuksi, kun on vain yksi konsoli. Siksikin tkinter-ratkaisu on ehkä parempi. Mutta idea siis on tässäkin se, että toistettava funktio käynnistää aina lopuksi erillisen prosessin/säikeen/munakellon, joka tietyn ajan kuluttua käynnistää funktion uudelleen.
Python:
import threading

def task():
    print(f"Täällä taas. Intervalli nyt {seconds} sekuntia")
    threading.Timer(seconds, task).start()

running = False
seconds : int
while True:
    s = input("Intervalli sekunteina? ")
    if s.isdecimal():
        seconds = int(s)
        if not running:
            running = True
            task()
 
Viimeksi muokattu:
Liittynyt
18.10.2016
Viestejä
476
Kyllä, tuolla threadingillä rokkaa. Minulla tuossa pääohjelmassa ei ole sinänsä mitään palautettavaa konsoliin, sillä lokiin kerrytän tietoa missä mennään/mitä tehty. Tein konsoliin pienen käyttöliittymän, mistä voi lukea lokia, asettaa intervalliajan, yms parametrejä pääohjelmaan. Johtuen allekirjoittaneesta (aka python-noob), minun pythonin rakenne on vähän väärä/epäpythonmäinen, joten en tuota timeriä käyttänyt sillä tuo pääohjelma sisälsi myös virhetilanneodotuksen (joka on 30min "jäähtymisaika"). Tuo toi toisen ongelman, jos tuon pääohjelman pysäyttää/lopettaa, niin piti threadingille antaa lisämuuttuja/juokseva numero joka käynnistykselle, jotta sen sai käynnistettyä useampaan otteeseen. Tosin näin jälkikäteen, tuolla timerillä sen kyllä olisi saaanut toimimaan kun olisin vain palauttanut virhetilanne booleanin pääohjelmasta ja sen ulkopuolella hoidellut odotuksen... Voi olla että teen tuosta rakenteesta oikeamman.
Jokatapauksessa iso kiitos vinkeistä!
 

hrk

Liittynyt
23.07.2017
Viestejä
1 730
Kyllä, tuolla threadingillä rokkaa. Minulla tuossa pääohjelmassa ei ole sinänsä mitään palautettavaa konsoliin, sillä lokiin kerrytän tietoa missä mennään/mitä tehty. Tein konsoliin pienen käyttöliittymän, mistä voi lukea lokia, asettaa intervalliajan, yms parametrejä pääohjelmaan. Johtuen allekirjoittaneesta (aka python-noob), minun pythonin rakenne on vähän väärä/epäpythonmäinen, joten en tuota timeriä käyttänyt sillä tuo pääohjelma sisälsi myös virhetilanneodotuksen (joka on 30min "jäähtymisaika"). Tuo toi toisen ongelman, jos tuon pääohjelman pysäyttää/lopettaa, niin piti threadingille antaa lisämuuttuja/juokseva numero joka käynnistykselle, jotta sen sai käynnistettyä useampaan otteeseen. Tosin näin jälkikäteen, tuolla timerillä sen kyllä olisi saaanut toimimaan kun olisin vain palauttanut virhetilanne booleanin pääohjelmasta ja sen ulkopuolella hoidellut odotuksen... Voi olla että teen tuosta rakenteesta oikeamman.
Jokatapauksessa iso kiitos vinkeistä!
Koska en tunne ongelmaasi, en ihan ymmärtänyt selitystäsi. Eikä minun tarvitsekaan; toivottavasti itse ymmärrät. Mutta tässä täydellisyyden vuoksi sellainen tkinter-versio, jossa on hieman parannettu käyttöliittymä. Tutkittavaksi, jos kiinnostaa.
Python:
import tkinter as tk

root = tk.Tk()
root.title("tämä on vain hassu esimerkki")
root.resizable(0, 0)
# oletusfontti
root.option_add("*font", "Calibri 16")

frame = tk.Frame(root)
frame.pack(padx=50, pady=(20,50))
tk.Label(frame, text="Toistuvaistyö", font="Calibri 24 bold").pack(anchor="w")
f = tk.Frame(frame)
f.pack(pady=10)
tk.Label(f, text="Väliaika: ").pack(side="left")
interval = tk.Entry(f, width=4)
interval.pack(side="left")
tk.Label(f, text=" sekuntia").pack(side="left")
button = tk.Button(frame, text="Aloita", command=lambda:start())
button.pack(anchor="w")

seconds = 10
running = False

interval.delete(0, 'end')
interval.insert(0, str(seconds))

def task():
    print("Tehdään jotain")
    print(f"Jatketaan noin {seconds} sekunnin kuluttua")
    root.after(1000 * seconds, task)

def start():
    global running, seconds
    s = interval.get()
    if s.isdecimal(): seconds = int(s)
    if not running:
        running = True
        button["text"] = "Jatka"
        task()

tk.mainloop()
 
Liittynyt
01.01.2018
Viestejä
1 117
JavaScript:
    const testCalorieRange = () => {
      if (formValues.targetCalories.some((i) => Number(i) < 1500)) {
        return <Heading>You should have at least 1500kcal a day</Heading>;
      }
    }
    
    testCalorieRange();
    return //something jsx
En ymmärrä miksei tuo testCalorieRange() ei koskaan palauta tuota rimpsua vaan aina komponentti palauttaa tuon //something jsx. Logilla pääsee kyllä tuon if lauseen sisälle silloin kuin kuuluukin mutta tuo <Heading> ei vaan palaudu millään.
 
Liittynyt
18.10.2016
Viestejä
54
JavaScript:
    const testCalorieRange = () => {
      if (formValues.targetCalories.some((i) => Number(i) < 1500)) {
        return <Heading>You should have at least 1500kcal a day</Heading>;
      }
    }
   
    testCalorieRange();
    return //something jsx
En ymmärrä miksei tuo testCalorieRange() ei koskaan palauta tuota rimpsua vaan aina komponentti palauttaa tuon //something jsx. Logilla pääsee kyllä tuon if lauseen sisälle silloin kuin kuuluukin mutta tuo <Heading> ei vaan palaudu millään.
Tuntematta nyt tarkemmin tuota koko koodia, niin miksi tuo ei palauttaisi tuota something.jsx viimeisenä?
Se on tuon funktion palautus, riippumatta siitä, että nuolifunktion sisällä halutaan välillä palauttaa jotain.

Voisiko tuo mennä
JavaScript:
const testCalorieRange = () => {
      if (formValues.targetCalories.some((i) => Number(i) < 1500)) {
        return <Heading>You should have at least 1500kcal a day</Heading>;
      } else {
        return // something jsx
      }
    }
    
    testCalorieRange();
 
Liittynyt
17.10.2016
Viestejä
4 589
JavaScript:
    const testCalorieRange = () => {
      if (formValues.targetCalories.some((i) => Number(i) < 1500)) {
        return <Heading>You should have at least 1500kcal a day</Heading>;
      }
    }
   
    testCalorieRange();
    return //something jsx
En ymmärrä miksei tuo testCalorieRange() ei koskaan palauta tuota rimpsua vaan aina komponentti palauttaa tuon //something jsx. Logilla pääsee kyllä tuon if lauseen sisälle silloin kuin kuuluukin mutta tuo <Heading> ei vaan palaudu millään.
Kyllähän se varmaan palauttaa sen, mutta koska sille palautteelle ei tehdä mitään niin ei se mihinkään silloin tulostu. testCalorieRange-kutsu pitäisi olla tuon return //something jsx sisällä jos sen haluaa tulostuvan.
 
Liittynyt
17.10.2016
Viestejä
14 542
En ymmärrä miksei tuo testCalorieRange() ei koskaan palauta tuota rimpsua vaan aina komponentti palauttaa tuon //something jsx. Logilla pääsee kyllä tuon if lauseen sisälle silloin kuin kuuluukin mutta tuo <Heading> ei vaan palaudu millään.
Sulla on vähän puutteellinen esimerkki että näkisi vähän enemmän, mitä oikeastaan haluat. Kuten tuossa jo sanottiin, se testCalorieRange(); kyllä evaluoituun oikeaksi elementiksi, mutta et palauta sitä tai käytä sitä palautusarvoa missään, joten sillä ei tehdä yhtään mitään. Se vaan katoaa käyttämättömänä. Haluat ehkä jotain tällaista, joka on aika yleinen tapa tehdä tuollaisia ehdollisia elementtejä:

Koodi:
function isEnoughCalories(calories) {
  if ( calories >= 1500) {
    return true;
  }
  return false;
}

const Foo = ({ calories }) => {
  return (
    <div>
      {!isEnoughCalories(calories) && <p>You should eat more!</p>}
      <p>This is shown regardless...</p>
    </div>
  );
}
 
Liittynyt
01.01.2018
Viestejä
1 117
joo kiitos teille, tuo return tosiaan puuttui tavallaan tuosta, nyt pitää tuota koodia vähän muokata että se toimii halutulla tavalla.
 
Liittynyt
01.01.2018
Viestejä
1 117
Onko teillä muuten preferenssiä restin ja graphqln välillä? Itse valitsin graphql ekaan web appiin, mutta täytyy sanoa että ole tullut vielä kertaakaan käytettyä mitään mistä graphql olisi ollut paljon hyötyä. Hirveä säätö on ollut vaan saada kaikki codegenit ja nexukset ynnä muut toimimaan.

Saako restillä helposti niin kuin type safetyn frontin ja backin välille? Siitä on kumminkin ollut hyötyä.
 
Liittynyt
14.12.2018
Viestejä
134
Tein kotiautomaatioon Windowsiin Visual Studiolla tuollaisen pienen gui:n, jossa kaksi nappulaa; start ja stop. Mulla on toisessa cpp -filessä funktio, jonka haluan pyörivän niin kauan kunnes stoppia painetaan. Saan sen käynnistymään kyllä hyvin starttinappulalla, mutta stoppia en saa toimimaan. Start-nappi on button1 ja lähettää nollan ja käynnistää while-loopin, stop-nappula on button2 ja lähettää ykkösen, jolloin while-loopin ei pitäisi pyöriä. Voi olla, että olen täysin hakoteillä tämän ratkaisuni kanssa, kun koitan välittää funktiolle numeroa, jonka mukaan while -looppi joko pyörii tai ei pyöri. Mikähän olisi koodareiden tapa tehdä tällainen?

form.h
Koodi:
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
     saturaatio_mittaus(0);     
    }
}
private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) {
     saturaatio_mittaus(1);
}
mittaus.cpp
Koodi:
int saturaatio_mittaus(int seis) {
  while(seis == 0) {
     //ajetaan koodia
  }
}
 
Liittynyt
10.01.2017
Viestejä
131
^sulla pitäisi olla esim globaali seis-muuttuja, joka sitten asetetaan ykköseksi tuossa button2_clickissä. Nythän se kutsuu samaa funktiota kun button1_click, joka siis pyörii koko ajan, eikä sen funktion seis-muuttuja muutu miksikään.
 
Liittynyt
14.12.2018
Viestejä
134
^ Kiitti! Koitanpa askarrella sillälailla tuota.

Edit: En saa näkymään form.h:ssa määritettyä seis-muuttujaa mittaus.cpp:ssä. Laitoin form.h:n alkuun "extern int seis;" ja klikkauksella asetetaan sille arvo. Mittaus.cpp sanoo: 'seis': undeclared identifier.

Edit2: Aa, piti vissiin vielä mittaus.cpp:ssä esitellä "int seis;" vaikka form.h:ssa oli jo "extern int seis;"?
 
Viimeksi muokattu:
Liittynyt
14.03.2019
Viestejä
879
Yritän kääntää Synergyä Ubuntu 21.10:lle seuraamalla näitä ohjeita: Compiling · symless/synergy-core Wiki

Tarvittavien pakettien asennus onnistui ja QT Creator 4.14.1 starttaa nätisti, mutta ohjeessa kohta "Edit the Qt kit "Environment" field under Tools -> Options -> Build & Run -> Kits and add BOOST_ROOT=/home/<user>/boost" aiheuttaa kysymysmerkkejä, kun en löydä tuolta Creatorista oikein paikkaa minne tuo pitäisi lisätä.

Polun seuraaminen onnistuu tuonne Tools -> Options asti ja sitten tökkää kun Build & Run alta ei löydy Kits -kohtaa, eikä myöskään Enviroment-kenttää. Enviroment ja Kits -ovat omia valintojaan vasemmassa reunassa, mutta niiden alta en myöskään löydä mitään järkevää paikka, minne tuo "BOOST_ROOT=/home/<user>/boost" voisi sijoittaa.

Eli mihin tuo oikein lisätään?

valikko.png
 
Liittynyt
17.10.2016
Viestejä
1 115
Yritän kääntää Synergyä Ubuntu 21.10:lle seuraamalla näitä ohjeita: Compiling · symless/synergy-core Wiki

Tarvittavien pakettien asennus onnistui ja QT Creator 4.14.1 starttaa nätisti, mutta ohjeessa kohta "Edit the Qt kit "Environment" field under Tools -> Options -> Build & Run -> Kits and add BOOST_ROOT=/home/<user>/boost" aiheuttaa kysymysmerkkejä, kun en löydä tuolta Creatorista oikein paikkaa minne tuo pitäisi lisätä.

Polun seuraaminen onnistuu tuonne Tools -> Options asti ja sitten tökkää kun Build & Run alta ei löydy Kits -kohtaa, eikä myöskään Enviroment-kenttää. Enviroment ja Kits -ovat omia valintojaan vasemmassa reunassa, mutta niiden alta en myöskään löydä mitään järkevää paikka, minne tuo "BOOST_ROOT=/home/<user>/boost" voisi sijoittaa.

Eli mihin tuo oikein lisätään?

Jos tarkoitus on vaan kääntää se niin mikset seuraa sitä ohjesivun lopussa olevaa kohtaa, CLI ja Linux? Ei tarvitse minkään vieraan IDEn kanssa värkätä.
 
Liittynyt
14.03.2019
Viestejä
879
Jos tarkoitus on vaan kääntää se niin mikset seuraa sitä ohjesivun lopussa olevaa kohtaa, CLI ja Linux? Ei tarvitse minkään vieraan IDEn kanssa värkätä.
Putkiaivot sanoo, että tuolla muuttujalla on jotain merkitystä kääntämisessä...

Pitää kokeilla, kunhan promillet laskee :).
 
Liittynyt
14.12.2018
Viestejä
134
Mulla on tässä kotiautomaatiojutussa Visual Studiolla tehty Windows GUI, jossa on toimiva sarjaporttikommunikaatio. Nyt minun pitäisi päästä lukemaan ja kirjoittamaan guissa (MyForm.h) avattua sarjaporttia mittaus.cpp:llä. Onko se mahdollista kun setuppi on tällähetkellä tällainen ja tuolla on noita privateja tms.? Vai pitääkö koittaa kaikki toiminnallisuus sisällyttää tuohon guin MyForm.h:n?

Gui jossa sarjaporttikommunikaatio toimii nyt:
form.h:
Koodi:
#pragma once
#include <fstream>
#include <iostream>
#include "mittaus.h"

namespace Project1 {
    using namespace System;
    using namespace System::IO::Ports;

public ref class MyForm : public System::Windows::Forms::Form
    {
    public:
        MyForm(void)
        {
            InitializeComponent();
            findPorts();
        }

protected:
private: System::IO::Ports::SerialPort^ serialPort1;

#pragma region Windows Form Designer generated code 
        void InitializeComponent(void)
        {
          this->components = (gcnew System::ComponentModel::Container());
          this->serialPort1 = (gcnew System::IO::Ports::SerialPort(this->components));
        }
#pragma endregion
    private: void findPorts(void)
    {
        array<Object^>^ objectArray = SerialPort::GetPortNames();
    }
private: System::Void button7_Click(System::Object^ sender, System::EventArgs^ e) {
    //add sender name
    String^ name = this->serialPort1->PortName;
    //grab text and store in send buffer
    String^ message = "hello";
    //write to serial
    if (this->serialPort1->IsOpen)
        this->serialPort1->WriteLine(message);
    else
        this->textBox2->Text = "Port Not Opened";
}
Mulle on epäselvää, että miten miten voisin lähettää esim. tuon hello -stringin mittaus.cpp:stä jo valmiiksi avattuun sarjaporttiin. Vai onnistuuko se mitenkään ilman isompaa remonttia?
 
Viimeksi muokattu:
Liittynyt
02.04.2017
Viestejä
15
Kuka muistaa, minkä nimiset kaksi kirjaa oli näillä spekseillä:

Joskus 2007-2009 lainasin kirjastosta kaksi suomenkielistä kirjaa peliohjelmointiin liittyen, jossa ekassa käytiin läpi koodipuolta, ja siinä tehtiin Assemblyllä "Haunted Mall" niminen merkkipohjainen esimerkkipeli. Tämä toinen kirja oli pidempi jossa käytiin tarkemmin läpi pelien design- ja suunnittelupuolta. Yhtään en muista tekijää, julkaisuvuotta, tai oliko kirjojen kannet valkoiset, mustat tai jonkun muun väriset.

EDIT: Ensimmäisen osan nimi on "Opeta itsellesi peliohjelmointi" ja se on julkaistu vuonna 1996. Ja tuo esimerkkipeli The Haunted Mall tehtiinkin VB:llä, eikä asmilla. Toinen kirja saattoi olla "Tehokäyttäjän opas - peliohjelmointi"
 
Viimeksi muokattu:

hrk

Liittynyt
23.07.2017
Viestejä
1 730
Mulla on tässä kotiautomaatiojutussa Visual Studiolla tehty Windows GUI, jossa on toimiva sarjaporttikommunikaatio. Nyt minun pitäisi päästä lukemaan ja kirjoittamaan guissa (MyForm.h) avattua sarjaporttia mittaus.cpp:llä. Onko se mahdollista kun setuppi on tällähetkellä tällainen ja tuolla on noita privateja tms.? Vai pitääkö koittaa kaikki toiminnallisuus sisällyttää tuohon guin MyForm.h:n?

Gui jossa sarjaporttikommunikaatio toimii nyt:
form.h:
Koodi:
#pragma once
#include <fstream>
#include <iostream>
#include "mittaus.h"

namespace Project1 {
    using namespace System;
    using namespace System::IO::Ports;

public ref class MyForm : public System::Windows::Forms::Form
    {
    public:
        MyForm(void)
        {
            InitializeComponent();
            findPorts();
        }

protected:
private: System::IO::Ports::SerialPort^ serialPort1;

#pragma region Windows Form Designer generated code
        void InitializeComponent(void)
        {
          this->components = (gcnew System::ComponentModel::Container());
          this->serialPort1 = (gcnew System::IO::Ports::SerialPort(this->components));
        }
#pragma endregion
    private: void findPorts(void)
    {
        array<Object^>^ objectArray = SerialPort::GetPortNames();
    }
private: System::Void button7_Click(System::Object^ sender, System::EventArgs^ e) {
    //add sender name
    String^ name = this->serialPort1->PortName;
    //grab text and store in send buffer
    String^ message = "hello";
    //write to serial
    if (this->serialPort1->IsOpen)
        this->serialPort1->WriteLine(message);
    else
        this->textBox2->Text = "Port Not Opened";
}
Mulle on epäselvää, että miten miten voisin lähettää esim. tuon hello -stringin mittaus.cpp:stä jo valmiiksi avattuun sarjaporttiin. Vai onnistuuko se mitenkään ilman isompaa remonttia?
Ehdotan että siirrät sarjaportin käsittelyn kokonaan unmanaged-puolelle (mittaus.cpp), jolloin managed c++ / winforms -osastoon jää vain GUI eli ne pari nappia. Tai sitten opiskelet aika paljon lisää. Tai kirjoitat koko homman uudelleen esimerkiksi pythonilla, jolloin neuvojakin löytyy netistä paremmin.
 
Liittynyt
14.12.2018
Viestejä
134
^Kiitti. Kerkesin alkaa koittamaan reference funktiokutsulla, mutta en tiedä saanko sillä toimimaan. Mutta opinpahan ehkä jotain uutta. Pitänee sen jälkeen koittaa siirtää sarjaporttihomma kokonaan sinne mittaus.cpp puolelle.
 

hrk

Liittynyt
23.07.2017
Viestejä
1 730
^Kiitti. Kerkesin alkaa koittamaan reference funktiokutsulla, mutta en tiedä saanko sillä toimimaan. Mutta opinpahan ehkä jotain uutta. Pitänee sen jälkeen koittaa siirtää sarjaporttihomma kokonaan sinne mittaus.cpp puolelle.
Koska kysymyksessä ilmeisesti on harrasteprojekti eikä ensisijaisesti c++-opiskelu, niin toistan ehdotukseni Pythonista. Sillä saa yksinkertaisen tkinter-käyttöliittymän helposti tehtyä, ja sarjaportinkin ohjelmointi on selkeää:


Jos kuitenkin haluat pitäytyä Microsoftin välineissä, niin .NET-käyttöliittymän ohjelmointi sujuu vähimmällä vaivalla C#-kielellä joko WPF- tai WinForms-kirjaston avulla, ja kaiken muunkin toiminnallisuuden voinee toteuttaa ilman c++-natiivikoodia.
 
Liittynyt
14.12.2018
Viestejä
134
Kiitti. Olen itseasiassa tehnyt tämän saman projektin aiemmin aika pitkälle Pythonilla, mutta nyt kun aloin lisäämään tähän toiminnallisuuksia niin taustalla oli halu myös oppia C++:aa. Pitää seuraavaksi koittaa myös noilla mainitsemillasi kielillä :)

Mutta taas törmäsin ongelmaan. Saan int arvot liikkumaan tiedostojen välillä, mutta en stringejä.

form.h:
Koodi:
extern int measureValue;
extern std::string measureType;

int main(){
    measureValue = 1;
    measureType = "testi"
}
mittaus.cpp:
Koodi:
int measureValue;
string measureType;

int measure() {
//Täällä kun lukee intin, se on oikein. Mutta kun lukee stringin, se on tyhjä.

}
Reference pass to function - systeemi ei tässä oikein toimi, kun funktioita mittaus.cpp:ssä on monia ja enkä haluaisi tehdä jokaiselle funktiolle omaa nappulaa, jolla lähetän stringin. Olisi hyvä, että jokainen funktio voisi lukea stringin samoin kuin lukee intinkin, mutta en oikein ymmärrä miksei extern string toimi samalla tavalla kuin int. Kääntäjä ei valita mitään, mutta string on tyhjä mittaus.cpp:ssä.
 
Liittynyt
14.10.2017
Viestejä
620
Kiitti. Olen itseasiassa tehnyt tämän saman projektin aiemmin aika pitkälle Pythonilla, mutta nyt kun aloin lisäämään tähän toiminnallisuuksia niin taustalla oli halu myös oppia C++:aa. Pitää seuraavaksi koittaa myös noilla mainitsemillasi kielillä :)

Mutta taas törmäsin ongelmaan. Saan int arvot liikkumaan tiedostojen välillä, mutta en stringejä.

form.h:
Koodi:
extern int measureValue;
extern std::string measureType;

int main(){
    measureValue = 1;
    measureType = "testi"
}
mittaus.cpp:
Koodi:
int measureValue;
string measureType;

int measure() {
//Täällä kun lukee intin, se on oikein. Mutta kun lukee stringin, se on tyhjä.

}
Reference pass to function - systeemi ei tässä oikein toimi, kun funktioita mittaus.cpp:ssä on monia ja enkä haluaisi tehdä jokaiselle funktiolle omaa nappulaa, jolla lähetän stringin. Olisi hyvä, että jokainen funktio voisi lukea stringin samoin kuin lukee intinkin, mutta en oikein ymmärrä miksei extern string toimi samalla tavalla kuin int. Kääntäjä ei valita mitään, mutta string on tyhjä mittaus.cpp:ssä.
No ainakin tuolta mainista puuttuu puolipiste stringin perästä. Luulisi kyllä että kääntäjä olisi tuon huomannut.
 
Liittynyt
15.10.2021
Viestejä
17
Kiitti. Olen itseasiassa tehnyt tämän saman projektin aiemmin aika pitkälle Pythonilla, mutta nyt kun aloin lisäämään tähän toiminnallisuuksia niin taustalla oli halu myös oppia C++:aa. Pitää seuraavaksi koittaa myös noilla mainitsemillasi kielillä :)

Mutta taas törmäsin ongelmaan. Saan int arvot liikkumaan tiedostojen välillä, mutta en stringejä.

form.h:
Koodi:
extern int measureValue;
extern std::string measureType;

int main(){
    measureValue = 1;
    measureType = "testi"
}
mittaus.cpp:
Koodi:
int measureValue;
string measureType;

int measure() {
//Täällä kun lukee intin, se on oikein. Mutta kun lukee stringin, se on tyhjä.

}
Reference pass to function - systeemi ei tässä oikein toimi, kun funktioita mittaus.cpp:ssä on monia ja enkä haluaisi tehdä jokaiselle funktiolle omaa nappulaa, jolla lähetän stringin. Olisi hyvä, että jokainen funktio voisi lukea stringin samoin kuin lukee intinkin, mutta en oikein ymmärrä miksei extern string toimi samalla tavalla kuin int. Kääntäjä ei valita mitään, mutta string on tyhjä mittaus.cpp:ssä.
Hei! Kokeilin tuota koodia seuraavilla täydennyksillä, eli ensin kirjoitan main funktiossa molemmat arvot, tulostan ne tuolla measure funktiossa, ylikirjoitan arvot ja lopuksi tulostan uudelleen main funktion lopussa:
mittaus.h:mittaus.cppmain.cpp
C++:
#pragma once

void measure();
C++:
#include <iostream>
#include <string>
#include "mittaus.h"

int measureValue;
std::string measureType;

void measure() {
    std::cout << measureValue << measureType << std::endl;
    measureValue = 2;
    measureType = "onnistui";
}
C++:
#include <iostream>
#include <string>
#include "mittaus.h"

extern int measureValue;
extern std::string measureType;

int main(){
    measureValue = 1;
    measureType = "testi";
    measure();
    std::cout << measureValue << measureType << std::endl;
}

g++ 11.2.1 kääntäjällä tulos:
$ g++ main.cpp mittaus.cpp
$ ./a.out
1testi
2onnistui


Koodi näyttäisi toimivan oletetulla tavalla. Voisiko ongelma olla nimialueissa? Oletko mahdollisesti määrittänyt saman muuttujanimen eri nimialueissa, jolloin kääntäjä ei näe ongelmaa, mutta muutat toisen nimialueen muuttujaa ja yrität sitten myöhemmin käyttää toista. Tässä esimerkki:

mittaus.hmittaus.cppmain.cpp
C++:
#pragma once
namespace mittaus {
void measure();
}
C++:
#include <iostream>
#include <string>
#include "mittaus.h"

int measureValue;
std::string measureType;

namespace mittaus {
std::string measureType;

void measure() {
    std::cout << measureValue << measureType << std::endl;
    measureValue = 2;
    measureType = "onnistui";
}
}
C++:
#include <iostream>
#include <string>
#include "mittaus.h"

extern int measureValue;
extern std::string measureType;

int main(){
    measureValue = 1;
    measureType = "testi";
    mittaus::measure();
    std::cout << measureValue << measureType << std::endl;
}

Tämän jälkeen tulos näyttää seuraavalta:

$ g++ main.cpp mittaus.cpp
$ ./a.out
1
2testi


Nuiden arvojen siirtoon voisi myös käyttää C++ oliopohjaisuutta ja olion attribuutteja eli muuttujia ja halutessa näille asettaja ja lukija (setter/getter) funktioita. Silloin kaikilla luokan funktioilla säilyy myös näkyvyys nuihin muuttujiin. Vielä jos nuo measureType tyypit on vakioita ei tuota string muotoista tyyppiä välttämättä tarvita vaan esimerkiksi enumeroitu tyyppi (enum) riitäisi hyvin:
Koodi:
enum measureType { temperature, speed, brightness };
 
Liittynyt
02.01.2017
Viestejä
18
Yritän kääntää Synergyä Ubuntu 21.10:lle seuraamalla näitä ohjeita: Compiling · symless/synergy-core Wiki

Tarvittavien pakettien asennus onnistui ja QT Creator 4.14.1 starttaa nätisti, mutta ohjeessa kohta "Edit the Qt kit "Environment" field under Tools -> Options -> Build & Run -> Kits and add BOOST_ROOT=/home/<user>/boost" aiheuttaa kysymysmerkkejä, kun en löydä tuolta Creatorista oikein paikkaa minne tuo pitäisi lisätä.

Polun seuraaminen onnistuu tuonne Tools -> Options asti ja sitten tökkää kun Build & Run alta ei löydy Kits -kohtaa, eikä myöskään Enviroment-kenttää. Enviroment ja Kits -ovat omia valintojaan vasemmassa reunassa, mutta niiden alta en myöskään löydä mitään järkevää paikka, minne tuo "BOOST_ROOT=/home/<user>/boost" voisi sijoittaa.

Eli mihin tuo oikein lisätään?

Veikkaan, että pitäs laittaa tänne:
Screenshot_20220110_123109.png
 
Liittynyt
14.12.2018
Viestejä
134
Hei! Kokeilin tuota koodia seuraavilla täydennyksillä, eli ...
Kiitti ystävällisestä ja perusteellisesta vastauksesta :) Olin tehnyt koodiin mokan, jolle olin jostain syystä täysin sokea. En osannut kopioida sitä edes tuohon ongelmakuvaukseen. Eli alustin tuon stringin vielä toistamiseen ja tässä taitaa extern nollautua:

Koodi:
extern int measureValue;
extern std::string measureType;

int main(){
    measureValue = 1;
    std::string measureType = "testi";   //eli "std::string" oli tässä liikaa :)
}
 
Liittynyt
17.10.2016
Viestejä
1 115
Kiitti ystävällisestä ja perusteellisesta vastauksesta :) Olin tehnyt koodiin mokan, jolle olin jostain syystä täysin sokea. En osannut kopioida sitä edes tuohon ongelmakuvaukseen. Eli alustin tuon stringin vielä toistamiseen ja tässä taitaa extern nollautua:

Koodi:
extern int measureValue;
extern std::string measureType;

int main(){
    measureValue = 1;
    std::string measureType = "testi";   //eli "std::string" oli tässä liikaa :)
}
Tarkalleenottaen tuossa ei externiin kosketa lainkaan, sen sijaan määritellään main-funktioon uusi muuttuja samalla nimellä ja alustetaan se. Tämä on näkyvissä ainoastaan tuon funktion scopessa.
 
Liittynyt
15.09.2021
Viestejä
8
Kysymys pythonin aloittelijalta.

Seuraavalla koodinpätkällä yritän saada listan eri harrastukset eli hobbyt erotettua pilkulla:

hobby_list = " "
for hobby in hobbies:
hobby_list += " ".join(hobby)


Print (hobby_list) kuitenkin tällä hetkellä tuottaa seuraanvanlaista tulosta c,o,d,i,n,gr,o,c,k, ,c,l,i,m,b,i,n,gr,e,a,d,i,n,g ja tavoitteena olisi coding, rock climbing, reading. Uskoakseni vika on join-methodin käytössä.
 

hrk

Liittynyt
23.07.2017
Viestejä
1 730
Huomaa myös, että join haluaa argumentikseen luettelon (list). Jos sille antaa merkkijonon (string), niin se käsittelee sen merkkien luettelona. Siten esim.

print(", ".join("huuhaa"))

tulostaa

h, u, u, h, a, a
 
Liittynyt
15.09.2021
Viestejä
8
Kiitos vastauksista! En nyt valitettavasti kuitenkaan saanut ratkaisua vielä pelittämään. Laitan tehtävänannon ja nykyisen vastauskyhäelmän kokonaisuudessaan. Elikkäs kyseessä on itse asiassa JSON tiedoston käsittely.

Tehtävänanto on seuraavanlainen: Let's have a look at a JSON file, which contains some information about students in the following format:
[
{
"name": "Peter Pythons",
"age": 27,
"hobbies": [
"coding",
"knitting"
]
},
{
"name": "Jean Javanese",
"age": 24,
"hobbies": [
"coding",
"rock climbing",
"reading"
]
}
]

Please write a function named print_persons(filename: str), which reads a JSON file in the above format, and prints the contents as shown below. The file may contain any number of entries.

Peter Pythons 27 years (coding, knitting)

Jean Javanese 24 years (coding, rock climbing, reading)

Minun koodinpätkä on tällä hetkellä seuraava:

import json

def print_persons(filename: str):
with open(filename) as new_file:
data = new_file.read()
persons = json.loads(data)

for person in persons:
name = person["name"]
age = person["age"]
hobbies = person["hobbies"]

hobby_list = " "
for hobby in hobbies:
hobby_list += hobby
print(f"{name} {age} years {(hobby_list)}")



Ongelmana on että tulostus tapahtuu seuraavasti tällä erää:

Peter Pythons 27 years codingknitting kun tavoite olisi Peter Pythons 27 years (coding, knitting).

Varmaan jokin aika simppeli ratkaisu löytyy, ja olen tuota join-metodia yrittänyt käyttää, mutta ei vaan lähde. millään.. Tänään pitäisi palauttaa ja hikeä alkaa jo pukkaamaan.
 
Liittynyt
08.02.2019
Viestejä
1 249
@Anduz koodia suuremmin muuttamatta, lisää nämä pilkut siihen hobby muuttujan perään loopissa, kun muodostat hobby_list muuttujaa ja trimmaa viimeinen pois tai käytä @Paapaa :n kertomaa tapaa joinata ne nippuun pilkkujen kanssa.
 
Liittynyt
17.10.2016
Viestejä
14 542
Ongelmana on että tulostus tapahtuu seuraavasti tällä erää:

Peter Pythons 27 years codingknitting kun tavoite olisi Peter Pythons 27 years (coding, knitting).
Mielestäni annoin sen vastauksen jo :D Eli ota tuo for-luuppi kokonaan pois. Et tarvitse sitä, et mitään hobby_list-muuttujaa.. Ja sulla taitaa olla normi- ja aaltosulkeet väärinpäin. Eli normisulkeet sun pitää printata, älä laita niitä aaltosulkeiden sisään. Aaltosulkeiden sisällä oleva interpoloidaan. Öbaut näin (en testannut):

Koodi:
...
hobbies = ", ".join(person["hobbies"])
print(f"{name} {age} years ({hobbies})")
 
Liittynyt
07.01.2021
Viestejä
678
Kannattaa muuten käyttää code-lohkoja, varsinkin Pythonin kanssa, niin säilyy sisennykset:
Koodi:
import json

def print_persons(filename: str):
with open(filename) as new_file:
  data = new_file.read()
persons = json.loads(data)

for person in persons:
  name = person["name"]
  age = person["age"]
  hobbies = person["hobbies"]
  hobby_list = " "
  for hobby in hobbies:
    hobby_list += hobby
  print(f"{name} {age} years {(hobby_list)}")
Ja tosiaan, joinaa tuo hobbies:
Koodi:
print(', '.join(hobbies))
 
Liittynyt
15.09.2021
Viestejä
8
Joo, kyllä! Vähillä unilla meni ajatukset hetkeksi jumiin, vastaus oli tosiaan jo @Paapaa ensimmäisessä kommentissa. Kiitos kaikille paljon avusta ja vinkeistä! Arvostan kovasti. Ja tehtävätkin nyt paketissa. Leppoisaa vkl:ää kaikille :)
 
Viimeksi muokattu:
Liittynyt
19.10.2016
Viestejä
359
Osaisikohan joku auttaa regexin kanssa?

Minulla on stringejä, jotka on suurinpiirtein tämän näköisiä:
"AAA111:Ford BBB-111:Volvo CCC-111:Naapurin auto"

Haluaisin saada tuosta siis nämä auton rekisterinumeroilta näyttävät stringit: "AAA111", "BBB-111", "CCC-111"
Eli siis kaikki teksti välilyönnin ja ":" merkin välillä. Lisäksi kaikki ennen ensimmäistä ":" merkkiä. "Rekisterinumeron" formaatti ja pituus on vapaa, mutta se ei voi sisältää merkkiä ":" tai välilyönti.

PHP on ohjelmointikieli, eli pitäisi sitä tukeva regex olla.
 
Viimeksi muokattu:
Liittynyt
02.11.2016
Viestejä
1 174
Osaisikohan joku auttaa regexin kanssa?

Minulla on stringejä, jotka on suurinpiirtein tämän näköisiä:
"AAA111:Ford BBB-111:Volvo CCC-111:Naapurin auto"

Haluaisin saada tuosta siis nämä auton rekisterinumeroilta näyttävät stringit: "AAA111", "BBB-111", "CCC-111"
Eli siis kaikki teksti välilyönnin ja ":" merkin välillä. Lisäksi kaikki ennen ensimmäistä ":" merkkiä. "Rekisterinumeron" formaatti ja pituus on vapaa, mutta se ei voi sisältää merkkiä ":" tai välilyönti.

PHP on ohjelmointikieli, eli pitäisi sitä tukeva regex olla.
Meniskö tällä.
PHP:
$s = "AAA111:Ford BBB-111:Volvo CCC-111:Naapurin auto";
preg_match_all("/[A-Z]{3}-?\d{3}/", $s, $m);
var_dump($m);
Edit. En lukenut kunnolla. Kaipaa vähän muokkausta.
 
Liittynyt
14.12.2016
Viestejä
257
Osaisikohan joku auttaa regexin kanssa?

Minulla on stringejä, jotka on suurinpiirtein tämän näköisiä:
"AAA111:Ford BBB-111:Volvo CCC-111:Naapurin auto"

Haluaisin saada tuosta siis nämä auton rekisterinumeroilta näyttävät stringit: "AAA111", "BBB-111", "CCC-111"
Eli siis kaikki teksti välilyönnin ja ":" merkin välillä. Lisäksi kaikki ennen ensimmäistä ":" merkkiä. "Rekisterinumeron" formaatti ja pituus on vapaa, mutta se ei voi sisältää merkkiä ":" tai välilyönti.

PHP on ohjelmointikieli, eli pitäisi sitä tukeva regex olla.
Näin nyt ainakin, $matches[2] sisältää rekkarit

PHP:
preg_match_all("/(([^:\s]+):)+/", "AAA111:Ford BBB-111:Volvo CCC-111:Naapurin auto", $matches);
 
Liittynyt
21.10.2016
Viestejä
9 054
Niin ja jos ei pakko ole regexiä käyttää, nii explode.
 
Viimeksi muokattu:
Liittynyt
07.01.2021
Viestejä
678
Miten JavaScriptissä pystyy tsekkaamaan onko muuttuja mappi? Minulla on tietorakenne joka näyttää jokseenkin tällaiselta:
Koodi:
{
  a: 1,
  b: "foo",
  c: { d: "bar", e: { f: 42}}
}
Ja pitäisi käydä tuo läpi. Periaatteessa pitäisi olla simppeli rekursio, mutta internet ei suostu paljastamaan oikeaa tapaa huomata, milloin arvo onkin toinen Mappi.
 
Liittynyt
07.01.2021
Viestejä
678
Saakohan seuraavan funktion params-parametrin tyypistä tulevaa valitusta (implisiittisesti any) pois? Funktio kyllä tuntuisi toimivan.
Koodi:
        const queryParams = (params, prefix = "") => {
            let retval: string[] = [];
            if (params) {
                if (prefix !== "") {
                    prefix = prefix + '_';
                }
                Object.keys(params).map(k => {
                    if (typeof params[k] === "object" && params[k] !== null) {
                        queryParams(params[k], prefix + k).map(value => retval.push(value));
                    } else {
                        retval.push(prefix + encodeURIComponent(k) + "=" + encodeURIComponent(params[k]));
                    }
                })
            }
            return retval;
        }
Tuo siis käsitelee tämän näköistä tietorakennetta (nuo vakiot on kaikki stringejä):
Koodi:
    const [lazyParams, setLazyParams]: [DataTablePFSEvent, (lazyParams: DataTablePFSEvent) => void] = React.useState<DataTablePFSEvent>({
        first: 0,
        rows: 50,
        page: 0,
        sortField: "name",
        sortOrder: 1,
        multiSortMeta: null,
        filters: {
            global: { value: null, matchMode: FilterMatchMode.CONTAINS },
            name: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] },
            dob: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] },
            dod: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] },
            nationality: { value: null, matchMode: FilterMatchMode.EQUALS },
            work_count: { value: null, matchMode: FilterMatchMode.EQUALS },
            story_count: { value: null, matchMode: FilterMatchMode.EQUALS },
            roles: { value: null, matchMode: FilterMatchMode.EQUALS }
        }
    });
Ajan tuon joinin läpi, niin saan tällaisen rimpsun (jos nyt jotakuta kiinnostaa):
Koodi:
first=0&rows=50&sortField=name&sortOrder=1&filters_global_value=null&filters_global_matchMode=contains&filters_name_operator=and&filters_name_constraints_0_value=null&filters_name_constraints_0_matchMode=startsWith&filters_dob_operator=and&filters_dob_constraints_0_value=null&filters_dob_constraints_0_matchMode=equals&filters_dod_operator=and&filters_dod_constraints_0_value=null&filters_dod_constraints_0_matchMode=equals&filters_nationality_value=null&filters_nationality_matchMode=equals&filters_work_count_value=null&filters_work_count_matchMode=equals&filters_story_count_value=null&filters_story_count_matchMode=equals&filters_roles_value=null&filters_roles_matchMode=equals&page=0&pageCount=101
 
Liittynyt
20.03.2017
Viestejä
184
Saakohan seuraavan funktion params-parametrin tyypistä tulevaa valitusta (implisiittisesti any) pois?
En tiedä typescriptistä mutta olisko koska tuossa kutsu funktiolle sekä parametrilla params että rekursiivisesti params[k], tyyppiä on vaikea päätellä.

Jos toi rakenne on vakio, voihan .filters käsitellä erikseen, jolloin tuo on helpompi analysoida.
 
Liittynyt
07.01.2021
Viestejä
678
Kokeilin tuota. Siis TS:ssä voi kyllä antaa useamman eri tyypin vaihtoehdoksi, mutta en saanut tuota toimimaan millään määrittelyillä. Ilman tyyppiä tuo siis toimii vaikka editori tuosta valittaakin.
 
Liittynyt
17.10.2016
Viestejä
14 542
Kokeilin tuota. Siis TS:ssä voi kyllä antaa useamman eri tyypin vaihtoehdoksi, mutta en saanut tuota toimimaan millään määrittelyillä. Ilman tyyppiä tuo siis toimii vaikka editori tuosta valittaakin.
Implicit any -varoitus tulee lintteriltä kun et anna mitään tyyppiä ja kääntäjä olettaa silloin tyypiksi any:n. Mutta jos tuo funktio syö ihan minkä tahansa objektin sisään (kuten jotkut funktiot syövät), niin oikea tapa on silloin eksplisiittisesti antaa se tyyppi, eli esim. (params: Object, prefix = ""). Tai jos se syö ihan mitä tahansa, niin sitten annat tyypiksi any:n, eksplisiittisesti.
 
Toggle Sidebar

Statistiikka

Viestiketjut
237 316
Viestejä
4 157 139
Jäsenet
70 407
Uusin jäsen
Eppupelaa

Hinta.fi

Ylös Bottom