Pieniä kysymyksiä ohjelmoinnista

Java 1.8 + JavaFX + Mavenilla asennettu SSHJ.

Käyttöliittymän komponentit sisältävän luokan (Gui.java) konstruktorissa luodaan olio, joka sisältää SSHJ-kirjaston toiminallisuuksia. Kun sovellus suoritetaan, se kaatuu virheilmoitukseen:
Koodi:
--- exec-maven-plugin:1.2.1:exec (default-cli) @ Testi ---
Exception in Application constructor
Exception in thread "main" java.lang.RuntimeException: Unable to construct Application instance: class personal.oma.Testi.Gui
   at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:907)
   at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(LauncherImpl.java:182)
   at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.reflect.InvocationTargetException
   at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
   at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
   at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
   at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
   at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$161(LauncherImpl.java:819)
   at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
   at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
   at java.security.AccessController.doPrivileged(Native Method)
   at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
   at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
   at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
   at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
   ... 1 more
Caused by: java.lang.NoClassDefFoundError: net/schmizz/sshj/transport/verification/HostKeyVerifier
   at personal.oma.Testi.Gui.<init>(Gui.java:42)
   ... 13 more
Caused by: java.lang.ClassNotFoundException: net.schmizz.sshj.transport.verification.HostKeyVerifier
   at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
   at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
   ... 14 more

Luodussa oliossa on eräs metodi, jota ei suoriteta ohjelman ajon missään vaiheessa. Metodista löytyy seuraava lause, johon ohjelman suoritus kaatuu:
Koodi:
ssh = new SSHClient();
ssh.addHostKeyVerifier(
                new HostKeyVerifier() {
            @Override
            public boolean verify(String s, int i, PublicKey publicKey) {
                return true;
            }
        });
Jos lause muutetaan lambda-muotoon, sovellus käynnistyy virheettä:
Koodi:
ssh = new SSHClient();
ssh.addHostKeyVerifier((String s, int i, PublicKey publicKey) -> true);

Miksi lambda-muodossa oleva lause toimii, mutta pitkässä muodossa oleva ei?
 
Virheilmoitus kertoo, että HostKeyVerifier-luokkaa ei löydy. Onko SSHJ-kirjasto class pathissa ajonaikana?

Miksi lambda-muodossa oleva lause toimii, mutta pitkässä muodossa oleva ei?
Tämä johtuu, että lambda-muodossa oleva toteutus ei käytä HostKeyVerifier-luokkaa, eikä sitä silloin siis yritetä ladata.
 
Virheilmoitus kertoo, että HostKeyVerifier-luokkaa ei löydy. Onko SSHJ-kirjasto class pathissa ajonaikana?
Kyllä sen pitäisi olla.

Jokin tuossa NetBeansin 'New -> Maven -> JavaFX Application':ssa mättää. Tein uuden projektin 'New -> Maven -> Java Application':n kautta, kopioin koodit, ja kaikki toimii niin kuin pitääkin.
 
Olisko jollain kokemusta Springboot/Spring Securityn käytöstä yhdessä jonkun reactjs/muun vastaavan erillisen frontin kanssa, niin että serveri tarjoaa vaan REST-apia jsonilla?

Tilanne:
- cors täysin sallittu, csrf-estot otettu pois: tokenin implementointia huolehdin kunhan ensimmäiset ongelmat on ratkaistu
- Spring securitystä korvattu AuthenticationSuccessHandler (vastaamaan 200 OK ja clearAuthenticationAttributes), AuthFailureHandler ja RESTAuthenticationEntryPoint.

Ongelma A:
- Avaan reactjs frontin npm serverillä localhost:3000 (palvelin kuuntelee localhost:8080)
- Lähetän form postina sisäänkirjautumisen serverille
- Serveri vastaa ok
- Seuraavat kutsut eivät kuitenkaan ole authentikoitu, koska serveri antaa 401 kun yritän resurssin lisäämistä/poistoa/editointia
---> Tismalleen sama frontend toimii, jos en avaa sitä erilliselle palvelimelle vaan paketoin sen ja localhost:8080 tarjoaa sen
(käytössä on whatvg-fetch ja kyllä, mukana on mode:cors sekä credentials: 'include')

Ongelma B:
- AuthenticationSuccessHandler ei näytä noudattavan globaalia @Configuration-filea corsin (allowedOrigins, allowedMethods) osalta, vaan joudun erikseen lisäämään responseen nämä tiedot... tämä liittynee ongelmaan A?

Ongelma C:
- Olisi oikeastaan parempi, että frontti ei lähettäisi lainkaan perinteistä form-dataa, vaan pelkkää jsonia
- Kirjoitin oman UsernamePasswordAuthenticationFilter, joka lukee tiedot jsonista ja palauttaa UsernamePasswordAuthenticationTokenin
- Sisällytän sen securityssä filterchainiin
- Filteri ottaa kyllä kiinni ja parsii jsonin oikeanlaiseksi, mutta nyt serveri ei haluakaan enää päästää vastausta success/failurehandlereihin vaan yrittää redirectata?!

Olisi tämä nettiohjelmointi aika paljon mielekkäämpää kun voisi unohtaa kaikenlaiset same-origin policyt, lokalisaatiot, aikavyöhykkeet sun muut...
 
Vastaten osiin omiin kysymyksiini:

Ongelma B vaati ratkaisuksi "http.cors();" määrittelyn Spring Securityn configiin. Tämä puolestaan ratkaisi heti ongelma A:n. Todella ärsyttävää magiaa.

Nyt siis ainoastaan C on enää ongelma, ja sekään ei pakollinen ratkaistava. Ongelma C toimii sekin nyt osittain: autentikaatio toimii... mutta ihan sama meneekö login oikella tai väärällä salasanalla, palvelin palauttaa 200 OK eikä mitään indikaatiota siitä, onnistuiko varsinainen kirjautuminen.
 
En osaa auttaa ongelmassa C, mutta CORS:n kanssa selviät huomattavasti helpommin ja ilman mystisiä ongelmia kun et vain käytä sitä.

Jos lopullisessa deploymentissa ei ole tarvetta CORS:lle, niin ei sitä kannata enabloida devauksessakaan. Aika monessa HTTP serverissä on tuki requestien proxyttamiselle. Tällä välttää kaikki CORS-ongelmat. Esim. http-server tarjoaa -P lipun
-P or --proxy Proxies all requests which can't be resolved locally to the given url.
 
Kyseessä oli harjoitustyö ennen varsinaisia työprojekteja, joten ongelmat corsin kanssa ja x-csrf-tokenien perusteet oli sikäli ainakin hyvä ymmärtää - tottahan tuo on, että tässä tapauksessa palvelin olisi aina voinut tarjota frontin productionissa ja corsia ei sikäli tarvita lainkaan.

Ongelma C:kin selvisi osittain: Koska korvaan UserAndPasswordFilterin, korvaan ilmeisesti samalla juuri sen FormLogin-filterin, johon nuo handlerit configuraatiossa liitetään -> luonnollisestikaan niihin handlereihin ei enää ohjata. Eli vissiin tarvitsee jotain lisäfilttereitä tai toteuttaa itse sen tilanteen tarkastamisen ja sitä kautta ohjaamisen eri handlereihin.
 
Pitäisi muuttaa kasa .pdf tiedostoja yhdeksi isoksi .pdf:äksi pythonilla. Tämä toimi hyvin, mutta sivut on aivan miten sattuu. sorted() pitäisi lyödä tuohon jotenkin ja sortedillekkin vissiin jotain lisäargumentteja, jotta pdf muodostuisi sivujen/tiedostojen nimissä olevien numeroiden järjestyksessä, mutta miten?

Koitin lisätä
Koodi:
def key_func(x):
        return os.path.split(x)[-1]

Koodi:
    for pdffile in sorted(glob(path + os.sep + '*.pdf'), key=key_func):  #aiemmin siis  for pdffile in glob(path + os.sep + '*.pdf'):
Mutta ei toiminut, alkoi valittaa indent erroreita vaikka koitin sisennyksiä pelkillä välilyönneillä mihin kohtiin tahansa.

Koodi:
from argparse import ArgumentParser
from glob import glob
from pyPdf import PdfFileReader, PdfFileWriter
import os

def merge(path, output_filename):
    output = PdfFileWriter()

    for pdffile in glob(path + os.sep + '*.pdf'):
        if pdffile == output_filename:
            continue
        print("Parse '%s'" % pdffile)
        document = PdfFileReader(open(pdffile, 'rb'))
        for i in range(document.getNumPages()):
            output.addPage(document.getPage(i))

    print("Start writing '%s'" % output_filename)
    with open(output_filename, "wb") as f:
        output.write(f)

if __name__ == "__main__":
    parser = ArgumentParser()

    # Add more options if you like
    parser.add_argument("-o", "--output",
                        dest="output_filename",
                        default="merged.pdf",
                        help="write merged PDF to FILE",
                        metavar="FILE")
    parser.add_argument("-p", "--path",
                        dest="path",
                        default=".",
                        help="path of source PDF files")

    args = parser.parse_args()
    merge(args.path, args.output_filename)

Edit: Ongelma ratkaistu.
Koodi:
from argparse import ArgumentParser
from PyPDF2 import PdfFileReader, PdfFileWriter
import os, glob
import shutil
import sys
 
target_folder = os.path.join(os.getcwd(),'pdfs')
print(os.getcwd())
 
def merge(path, output_filename):
    output = PdfFileWriter()
 
    for file in sorted(glob.glob(os.path.join(target_folder,'page[0-9]*.pdf')), key=lambda name: int(os.path.basename(name)[4:-4])):
        if file == output_filename:
            continue
        print("Parse '%s'" % file)
        document = PdfFileReader(open(file, 'rb'))
        for i in range(document.getNumPages()):
            output.addPage(document.getPage(i))
 
    print("Start writing '%s'" % output_filename)
    with open(output_filename, "wb") as f:
        output.write(f)
 
def move_files_preprocess():
    if not os.path.exists(target_folder):
        os.makedirs(target_folder)
 
    for file in glob.glob('page[0-9]*.pdf'):
        #print('Moving {file} to path {path}'.format(file=file, path=target_folder))
        shutil.move(file, os.path.join(target_folder, file))
 
def instantiate_parser():
        parser = ArgumentParser()
 
        # Add more options if you like
        parser.add_argument("-o", "--output",
                            dest="output_filename",
                            default="merged.pdf",
                            help="write merged PDF to FILE",
                            metavar="FILE")
        parser.add_argument("-p", "--path",
                            dest="path",
                            default=".",
                            help="path of source PDF files")
 
        args = parser.parse_args()
        merge(args.path, args.output_filename)
 
 
def main(argv):
        move_files_preprocess()
        instantiate_parser()
 
 
if __name__ == "__main__":
    sys.exit(main(sys.argv))
 
Viimeksi muokattu:
Front-end JS on mulle hieman vierasta maailmaa. Auttakaa joku miten text/html tyyppisen document.createElement()-metodilla luodun object-elementin saa tottelemaan pääsivuston CSS:ää? Täytyykö tuon objectin sisältää oma viittauksensa CSS-tiedostoon?
 
Pitäisi muuttaa kasa .pdf tiedostoja yhdeksi isoksi .pdf:äksi pythonilla. Tämä toimi hyvin, mutta sivut on aivan miten sattuu. sorted() pitäisi lyödä tuohon jotenkin ja sortedillekkin vissiin jotain lisäargumentteja, jotta pdf muodostuisi sivujen/tiedostojen nimissä olevien numeroiden järjestyksessä, mutta miten?

Koitin lisätä
Koodi:
def key_func(x):
        return os.path.split(x)[-1]

Koodi:
    for pdffile in sorted(glob(path + os.sep + '*.pdf'), key=key_func):  #aiemmin siis  for pdffile in glob(path + os.sep + '*.pdf'):
Mutta ei toiminut, alkoi valittaa indent erroreita vaikka koitin sisennyksiä pelkillä välilyönneillä mihin kohtiin tahansa.

Koodi:
from argparse import ArgumentParser
from glob import glob
from pyPdf import PdfFileReader, PdfFileWriter
import os

def merge(path, output_filename):
    output = PdfFileWriter()

    for pdffile in glob(path + os.sep + '*.pdf'):
        if pdffile == output_filename:
            continue
        print("Parse '%s'" % pdffile)
        document = PdfFileReader(open(pdffile, 'rb'))
        for i in range(document.getNumPages()):
            output.addPage(document.getPage(i))

    print("Start writing '%s'" % output_filename)
    with open(output_filename, "wb") as f:
        output.write(f)

if __name__ == "__main__":
    parser = ArgumentParser()

    # Add more options if you like
    parser.add_argument("-o", "--output",
                        dest="output_filename",
                        default="merged.pdf",
                        help="write merged PDF to FILE",
                        metavar="FILE")
    parser.add_argument("-p", "--path",
                        dest="path",
                        default=".",
                        help="path of source PDF files")

    args = parser.parse_args()
    merge(args.path, args.output_filename)

Kellään vinkkejä?
Minulla toimi ainakin koodi tästä suoraan kopioituna, ehkä siellä on tabulaattori jossain? Edit. Siinä kohtaa, mihin lisäsit key_func-funktion. Nämä kooditagit taitaa tehdä jotain tabeille, taitaa muuttaa välilyönneiksi.

Jos PDF:n haluttu järjestys on tiedostonimien perässä, niin sorted():n key-funktio voisi olla jotain tällaista.
Koodi:
import re

def key_func(x):
    filename = os.path.split(x)[-1]
    m = re.match('[^\d]*(?P<num>\d+)\.pdf$', filename)
    if not m:
        return filename
    return int(m.group('num'))
Patternia pitää muuttaa sen mukaan miten tiedostot on nimetty.
 
Front-end JS on mulle hieman vierasta maailmaa. Auttakaa joku miten text/html tyyppisen document.createElement()-metodilla luodun object-elementin saa tottelemaan pääsivuston CSS:ää? Täytyykö tuon objectin sisältää oma viittauksensa CSS-tiedostoon?

Tarkoittanet tilannetta, jossa haluat viitata elementtiin esim. luokkaselektorilla. Tässä esimerkki:

Koodi:
let button = document.createElement('button');
button.setAttribute('className', 'myButtonClass');
button.setAttribute('id', 'myButtonId');

Tällöin CSS:
Koodi:
button {
  font-size: 20px;
}

.myButtonClass {
  background-color: blue;
}

#myButtonId {
  border-radius: 10px;
}

on validia kauraa.
 
Tarkoittanet tilannetta, jossa haluat viitata elementtiin esim. luokkaselektorilla. Tässä esimerkki:

Koodi:
let button = document.createElement('button');
button.setAttribute('className', 'myButtonClass');
button.setAttribute('id', 'myButtonId');

Tällöin CSS:
Koodi:
button {
  font-size: 20px;
}

.myButtonClass {
  background-color: blue;
}

#myButtonId {
  border-radius: 10px;
}

on validia kauraa.

Hmmm, tarkoitan siis esim. tämmöistä tilannetta:

Koodi:
...
    <head>
        <style>
            * {
                font-family: "Courier New";
                font-size: 25px;
            }
        </style>
        <script>
            function loadit() {
                c = document.createElement("object");
                c.setAttribute("type", "text/html");
                c.setAttribute("data", "1.html");
                document.getElementById("content").appendChild(c);  
            }
        </script>
    </head>
...

Bodyssä siis div-elementti id:llä "content", jonne loadit() lisää filen "1.html" sisällön, joka sisältää esim. "<p>qwerty</p>". Headin style ei nyt pure tuohon p-elementtiin.
 
Viimeksi muokattu:
^Heitän ilman parempaa tietoa villin veikkauksen, että object-tyyppiset elementit ladataan yleensä sillä tarkoituksella, että ne ovat itsenäisiä kokonaisuuksia ja että niiden sisältö näytetään siksi sellaisenaan. Näin ollen normaalit tyylimäärittelyt eivät pure niihin vaan ne tarvitsevat omansa.
 
^Heitän ilman parempaa tietoa villin veikkauksen, että object-tyyppiset elementit ladataan yleensä sillä tarkoituksella, että ne ovat itsenäisiä kokonaisuuksia ja että niiden sisältö näytetään siksi sellaisenaan. Näin ollen normaalit tyylimäärittelyt eivät pure niihin vaan ne tarvitsevat omansa.

No tämä kyllä vaikuttaa ihan loogiselta, joten tällä mennään. Kiitos vastauksesta.
 
Olisi vähän python-ongelmaa... Eli kakkossarjan pythonilla homma toimii kuin junan vessa mutta pythonin 3-versiolla antaa virheilmoitusta, josta en tullut googlailemalla yhtään viisaammaksi vaikka kokeilin joitakin netistä löytyneitä vinkkejä. Koodi on siis käännetty 2to3 -skriptillä python3-muotoon.

Koodi ei siis ole omaa ja tarkoituksena olisi saada se toimimaan kolmospyyttonissa. Tuo liittyy omaan isompaan projektiin joka ohjailee vähän kaikenlaisia vekottimia ja olisi tarkoitus saada vähän järkevöitettyä tuota hässäkkää koska se nykyisellään koostuu sekalaisesta kasasta eri ohjelmointikieliä ja skriptejä. Tuo osuus siis lähettää LIRCin kautta infrapunakomentoja laitteille.

Virheilmoitus:
Koodi:
Traceback (most recent call last):
  File "testi.py3", line 4, in <module>
    print(local_lirc.send_once('KEY_3','NETGEM'))
  File "/home/pi/testing/lircsend3.py", line 140, in send_once
    return self._send_packet(command)
  File "/home/pi/testing/lircsend3.py", line 86, in _send_packet
    self._s.sendall(command)
TypeError: 'str' does not support the buffer interface

Itse ongelmakoodi spoilerissa:
Koodi:
"""
lirc-send.py
Provides a Python Send API for the lirc libraries
Copyright (C) 2015 peter.cowan@cantab.net

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.


Realistically this code shouldn't be required since lirc 0.9.2 has a
C API to send IR and the very capable python-lirc project should be
extended. Sadly lirc 0.9.2  isn't yet available for Raspian so
falling back to raw socket communication... delicious.
"""
import socket
from threading import Lock

ENCODING = 'utf-8'
STRING_BUFFER_LEN = 256
DEFAULT_UNIX_SOCKET = "/var/run/lirc/lircd"
LOCAL_HOST_IP = "127.0.0.1"
DEFAULT_LIRC_PORT = 8765

class LircSend:
    """Use the class methods instead"""
    _s = None
    _init = False
    _lock = Lock()
    _debug = False
    
    def __init__(self, location = None, port = None):
        if not port:
            self._s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
            self._s.connect(DEFAULT_UNIX_SOCKET)
        else:
            self._s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self._s.connect((location, port))
        self._init = True
    
    def set_debug(self, debug):
        if debug:
            self._debug = True
        else:
            self._debug = False
    
    def destroy(self):
        try:
            self._lock.acquire()
            self._s.close()
            self._s = None
            self._init = False
        finally:
            self._lock.release()
    
    @classmethod
    def create_local(cls, location = None):
        if not location:
            location = DEFAULT_UNIX_SOCKET
        return cls(location)

    @classmethod
    def create_remote(cls, location = None, port = None):
        if not location:
            location = LOCAL_HOST_IP
        if not port:
            port = DEFAULT_LIRC_PORT
        return cls(location, port)

    """Internal method for communicating with LIRC"""
    def _send_packet(self, command):
        command = command + "\n"
        if not self._init:
            raise ValueError("Object has been destroyed")
        try:
            self._lock.acquire()
            self._s.sendall(command)
            buf = ""
            data = ""
            """The socket caches IR recieve requests, we need to ignore them"""
            while not "BEGIN" in data:
                data = self._s.recv(256)
                if self._debug:
                    print(data)
                    print((":".join("{}[{:02x}]".format(c, ord(c)) for c in data)))
            buf += data
            
            """Start reading sensible content"""
            while not buf.endswith("END\n"):
                data = self._s.recv(256)
                buf += data
                if self._debug:
                    print(data)
            return self._parse(buf)
        finally:
            self._lock.release()
    
    def _parse(self, content):
        lines = content.split("\n")
        command = None
        success = True
        payload = []
        started = False
        payload_parse = False
        for line in lines:
            if line == "BEGIN":
                if not started:
                    started = True
                    payload = []
            elif line == "SUCCESS" or line == "ERROR":
                if line == "ERROR":
                    success = False
                command = '\n'.join(payload)
                payload = []
            elif line == "DATA":
                payload_parse = True
                payload = []
            elif line == "END":
                if payload_parse:
                    """Dump all elements except the first into the payload"""
                    payload = payload[1:len(payload)]
                    pass
                break
            else:
                if started:
                    payload.append(line)
        return LircResponse(command, success, payload)

    def send_once(self, key, remote, repeat = 1):
        command = "SEND_ONCE %s %s %d" % (remote, key, repeat)
        return self._send_packet(command)

    def send_start(self, key, remote):
        command = "SEND_START %s %s" % (remote, key)
        return self._send_packet(command)

    def send_stop(self):
        command = "SEND_STOP"
        return self._send_packet(command)
        
    def list_remotes(self):
        command = "LIST"
        return self._send_packet(command).payload
    
    def list_remote_codes(self, remote):
        command = "LIST %s" % remote
        lirc_result = self._send_packet(command)
        if lirc_result.success:
            command_dict = {}
            for line in lirc_result.payload:
                line_split = line.split(" ")
                key = " ".join(line_split[1:len(line_split)])
                value = line_split[0]
                command_dict[str(key)] = value
            return command_dict
        return None

    def send_simulate(self, scancode, repeat, keysym, remote):
        command = "SIMULATE {0:0>16x} {1:0>2d} {2:s} {3:s}".format(scancode, repeat, keysym, remote)
        return self._send_packet(command)

class LircResponse:
    def __init__(self, command, success, payload):
        self.command = command
        self.success = success
        self.payload = payload

ja vielä testikoodinpätkä millä olen tuota kokeillut:
Koodi:
from lircsend import LircSend

local_lirc = LircSend.create_local()
print(local_lirc.send_once('KEY_3','NETGEM'))
local_lirc.destroy()
 
Näköjään Python2:ssa socket.sendall():n argumentti pitää olla str-tyyppinen ja Python3:ssa taasen bytes-tyyppinen. Kokeile muuttaa, olisiko tuo rivi 86, katsoin Githubista, seuraavaksi. Voi olla ettei ole ainut kohta, missä tuon muutoksen joutuu tekemään tai ehkä toisin päin jossain muualla.
Koodi:
self._s.sendall(command.bytes())
 
Ei tuo korjannut tuota mutta ainakin nyt ollaan jo lähempänä ongelman ydintä kun virheilmoitus vaihtui. Herjaa edelleen samasta rivistä mutta nyt seuraavanlainen virhe:
Koodi:
AttributeError: 'str' object has no attribute 'bytes'
Kun tuon muutti muotoon:
Koodi:
self._s.sendall(bytes(command,"utf-8"))
niin homma meni pykälällä eteenpäin. Tosin, nyt mä tajusin tuon homman idean ja varmaan saan tapettua loput bugit tuosta ihan itsekseni...

Nyt siis tuo jo lähettää IR-datan eteenpäin mutta herjaa myöhemmin rivillä 90:
Koodi:
TypeError: Type str doesn't support the buffer API

No, mutta tuo saa jäädä hautumaan aamuun, jos sitä koodailisi välipalaksi IKEA Trådfri-tuen kodinhallintajärjestelmään...
 
Ei tuo korjannut tuota mutta ainakin nyt ollaan jo lähempänä ongelman ydintä kun virheilmoitus vaihtui. Herjaa edelleen samasta rivistä mutta nyt seuraavanlainen virhe:
Koodi:
AttributeError: 'str' object has no attribute 'bytes'
Kun tuon muutti muotoon:
Koodi:
self._s.sendall(bytes(command,"utf-8"))
niin homma meni pykälällä eteenpäin. Tosin, nyt mä tajusin tuon homman idean ja varmaan saan tapettua loput bugit tuosta ihan itsekseni...
str.bytes() olikin Python2:sta. Muistin väärin ja kokeilinkin sitä vielä Python2-tulkissa. encode- ja decode-metodit ne taisi olla, joita käytetään Python3:ssa. Ei tule paljoa ohjelmoitua Pythonilla.
 
CSS käyttöä olen alkanut opettelemaan ja simppeleitä nettisivuja tehnyt. Pari ongelmaa vain ihmetyttää. Käsitteet ihan hukassa, kun aloittelija olen.

Esimerkiksi kuvassa olen määritellyt Labelin arvoja. Kuitenkin jos tuon leveyden jälkeen (punainen ympyrä) kirjoittaa ihan mitä tahansa, vaikka yhden kirjaimen, kumoutuvat kaikki muut annetut arvot. Tässä tapauksessa block ja leveys. Mistä ihmeestä tuo johtuu? Pakko aloittaa kokonaan uusi alue (millä nimellä noita kutsutaan?), johon kirjoitan seuraavat muutokset Labelille.

8t3ykgm.jpg


Chromella olen muokannut CSS:ää, kun sillä saa mukavasti muutokset heti näkymään. Kun olen tehnyt muutokset, klikkaan sources kohdasta css. tiedostoa ja valitsen "save as" ja korvaan sen uudella. Kuitenkaan sivusto ei aina osaa ottaa sitä käyttöön ja html-tekstistä pitää käydä vaihtamassa css-tiedoston sijainti/nimi johonkin muuhun ja sitten takaisin. Pari kertaa taas css-muotoilu on mennyt aivan sekaisin tallentaessa. Pelkkä save ei tallenna muutoksia. Mitä teen väärin?
 
Esimerkiksi kuvassa olen määritellyt Labelin arvoja. Kuitenkin jos tuon leveyden jälkeen (punainen ympyrä) kirjoittaa ihan mitä tahansa, vaikka yhden kirjaimen, kumoutuvat kaikki muut annetut arvot. Tässä tapauksessa block ja leveys. Mistä ihmeestä tuo johtuu? Pakko aloittaa kokonaan uusi alue (millä nimellä noita kutsutaan?), johon kirjoitan seuraavat muutokset Labelille.

8t3ykgm.jpg
Puolipiste puuttuu 30px:n perästä.

Edit. Voit tarkistaa CSS:n syntaksin vaikka tällä palvelulla: The W3C CSS Validation Service

Chromella olen muokannut CSS:ää, kun sillä saa mukavasti muutokset heti näkymään. Kun olen tehnyt muutokset, klikkaan sources kohdasta css. tiedostoa ja valitsen "save as" ja korvaan sen uudella. Kuitenkaan sivusto ei aina osaa ottaa sitä käyttöön ja html-tekstistä pitää käydä vaihtamassa css-tiedoston sijainti/nimi johonkin muuhun ja sitten takaisin. Pari kertaa taas css-muotoilu on mennyt aivan sekaisin tallentaessa. Pelkkä save ei tallenna muutoksia. Mitä teen väärin?
En tiedä, mutta jos päivittää sivun, niin muutokset eivät tallennu minnekään. En tiedä miten Chrome ottaa käyttöön tallennetun CSS-tiedoston. Suosittelen jotain toista, kätevämpää tapaa opetella CSS:ä.
 
CSS käyttöä olen alkanut opettelemaan ja simppeleitä nettisivuja tehnyt. Pari ongelmaa vain ihmetyttää. Käsitteet ihan hukassa, kun aloittelija olen.

Esimerkiksi kuvassa olen määritellyt Labelin arvoja. Kuitenkin jos tuon leveyden jälkeen (punainen ympyrä) kirjoittaa ihan mitä tahansa, vaikka yhden kirjaimen, kumoutuvat kaikki muut annetut arvot. Tässä tapauksessa block ja leveys. Mistä ihmeestä tuo johtuu? Pakko aloittaa kokonaan uusi alue (millä nimellä noita kutsutaan?), johon kirjoitan seuraavat muutokset Labelille.

8t3ykgm.jpg


Chromella olen muokannut CSS:ää, kun sillä saa mukavasti muutokset heti näkymään. Kun olen tehnyt muutokset, klikkaan sources kohdasta css. tiedostoa ja valitsen "save as" ja korvaan sen uudella. Kuitenkaan sivusto ei aina osaa ottaa sitä käyttöön ja html-tekstistä pitää käydä vaihtamassa css-tiedoston sijainti/nimi johonkin muuhun ja sitten takaisin. Pari kertaa taas css-muotoilu on mennyt aivan sekaisin tallentaessa. Pelkkä save ei tallenna muutoksia. Mitä teen väärin?
Widthin lopusta puuttuu puolipiste joten tuo hajoaa kun lisäät seuraavalle riville tekstiä, nyt tuo kaarisulku kattaa sen puolipisteen

Ja ctrl-f5 lataa resurssit uusiksi
 
Tietenkin oli noin helppo ratkaisu tuohon ekaan ongelmaan. Web developerilla kyllä tarkastan html:n ja css:n virheet aina lopussa ja korjaan ne :facepalm:

Nyt taas tänään tuo Chromen CSS:n tallennus toimii hyvin. Muutokset koodiin tulevat reaaliajassa ja tallennus toimii nopeasti ja helposti. Joskus tuo vain ei suostu kuitenkaan toimimaan kunnolla.
 
Muutama pieni kysymys Python 3:sta.

Ohjelmointi ei ole juurikaan hallussa ja olen omaksi ilokseni yrittänyt tutustua Python 3:seen.

Yritän lukea xml tiedostoa ElementTree:n avulla. Onnistuin jotakin tietoa saamaan jo irti, mutta kuinka pystyn hakemaan esimerkiksi tuosta tuon "jouko" arvon "456"?

<Tietoja>
<muuttuja name="ari" value="123" />
<muuttuja name="jouko" value="456" />
<muuttuja name="pekka" value="789" />
</Tietoja>

Täytyykö xml-tiedostot tallentaa ensin koneelle paikallisesti ja sen jälkeen vasta tutkia sen sisältämiä tietoja vai pystyykö tuon lukemaan suoraan urlista tallentamatta sitä?
 
Yritän lukea xml tiedostoa ElementTree:n avulla. Onnistuin jotakin tietoa saamaan jo irti, mutta kuinka pystyn hakemaan esimerkiksi tuosta tuon "jouko" arvon "456"?

<Tietoja>
<muuttuja name="ari" value="123" />
<muuttuja name="jouko" value="456" />
<muuttuja name="pekka" value="789" />
</Tietoja>

Täytyykö xml-tiedostot tallentaa ensin koneelle paikallisesti ja sen jälkeen vasta tutkia sen sisältämiä tietoja vai pystyykö tuon lukemaan suoraan urlista tallentamatta sitä?

Ei tarvitse tallentaa, mutta se data pitää hakea ensin tietenkin netistä. Tsekkaapa täältä, kuinka XPath toimii:

20.5. xml.etree.ElementTree — The ElementTree XML API — Python 3.6.3 documentation

Haku url:stä onnistuu helposti esim. requests-kirjastolla. Voin näyttää illemmalla esimerkkiä jos joku muu ei ole ehtinyt ensin.
 
Tuo value+"256" on elementin attribuutti value. Se on siis elementin ominaisuus, ei itsessään elementti. Siitä se lähtee.

Lähetetty minun Nexus 6P laitteesta Tapatalkilla
 
Muutama pieni kysymys Python 3:sta.

Ohjelmointi ei ole juurikaan hallussa ja olen omaksi ilokseni yrittänyt tutustua Python 3:seen.

Yritän lukea xml tiedostoa ElementTree:n avulla. Onnistuin jotakin tietoa saamaan jo irti, mutta kuinka pystyn hakemaan esimerkiksi tuosta tuon "jouko" arvon "456"?

<Tietoja>
<muuttuja name="ari" value="123" />
<muuttuja name="jouko" value="456" />
<muuttuja name="pekka" value="789" />
</Tietoja>

Täytyykö xml-tiedostot tallentaa ensin koneelle paikallisesti ja sen jälkeen vasta tutkia sen sisältämiä tietoja vai pystyykö tuon lukemaan suoraan urlista tallentamatta sitä?

Nopea esimerkki jo aiemmissa kommenteissa mainituilla kirjastoilla. Data Pastebinissä.

Koodi:
import requests
from xml.etree import ElementTree

url = 'https://pastebin.com/raw/huS8YPbJ'
r = requests.get(url)

tree = ElementTree.fromstring(r.content)
for c in tree:
    print(c.tag, c.attrib)

Ja sitten esim. tuon joukon valuen saisi tuosta datasta suoraan esimerkiksi näin:

Koodi:
jouko = tree.find(".//*[@name='jouko']")
print(jouko.get("value"))
 
Viimeksi muokattu:
Hei io-tekkiläiset!

Olen harjoittelemassa Buffer Overflow attackia Computerphilen jalanjäljissä.

Ongelmaksi muodostuu, kuinka saan koostettua kohdassa https://youtu.be/1S0aBV-Waeo?t=9m49s esiteltyä konesyntaksia, jolla saisin esim. terminalin auki? Pystyn tietenkin kirjoittamaan lyhyen C-kielisen ohjelman, joka käynnistää ohjelman, mutta kääntäjä saa siitäkin luotua monen kilotavun paketin vs. videolla nähtävä muutama tavu.

Käyttöjärjestelmänä Ubuntu.

Pahoittelut hieman vajavaisesta aloituksesta. Palaan asiaan parin tunnin kuluttua. Ja kiitos jo etukäteen, jos jaksaa nähdä vaivaa ja vastata.
 
Hei io-tekkiläiset!

Olen harjoittelemassa Buffer Overflow attackia Computerphilen jalanjäljissä.

Ongelmaksi muodostuu, kuinka saan koostettua kohdassa https://youtu.be/1S0aBV-Waeo?t=9m49s esiteltyä konesyntaksia, jolla saisin esim. terminalin auki? Pystyn tietenkin kirjoittamaan lyhyen C-kielisen ohjelman, joka käynnistää ohjelman, mutta kääntäjä saa siitäkin luotua monen kilotavun paketin vs. videolla nähtävä muutama tavu.

Käyttöjärjestelmänä Ubuntu.

Pahoittelut hieman vajavaisesta aloituksesta. Palaan asiaan parin tunnin kuluttua. Ja kiitos jo etukäteen, jos jaksaa nähdä vaivaa ja vastata.
Heitän hatusta, että kirjoitat assembly-kielellä ohjelman, joka avaa terminaalin. Käännä se, katso mitä tulee ulos, ja siinä on koodisi. Sama voi onnistua kirjoittamalla vastaava C-funktio ja katsomalla, millaista konekieltä kääntäjä generoi funktiolle. Senkin pitäisi ajaa sama asia. Joka tapauksessa konekielen lukeminen lienee välttämätöntä. Käsittääkseni on olemassa myös sovelluksia, joilla näkee konekielen ja lähdekoodin tai ainakin assembly-kielen välisen vastaavuuden, mikä voi olla käytännössä välttämätöntä (harva varmaan osaa varsinaista konekieltä).
 
Kannattaako yleensä MySQL tietokannan data jakaa useampaan tauluun, vai kasvattaa taulujen sarakkeiden määrää? Eli laitanko esimerkiksi asunnon osaketiedot(määrä, osakeryhmän alkuosa, loppuosa) omaan tauluun, joka liitetään asuntoon, vai suoraan asuntotauluun?
 
Kannattaako yleensä MySQL tietokannan data jakaa useampaan tauluun, vai kasvattaa taulujen sarakkeiden määrää? Eli laitanko esimerkiksi asunnon osaketiedot(määrä, osakeryhmän alkuosa, loppuosa) omaan tauluun, joka liitetään asuntoon, vai suoraan asuntotauluun?

En ole tietokanta-asiantuntija, mutta tuo riippunee käyttötarkoituksesta ja ehkä siitäkin onko yhteydet 1-to-1 vai 1-to-many. Jälkimmäisessä tapauksessa näkisin suuremmat hyödyt erillisissä tauluissa. Viisaammat korjatkoot!

Yleensä sitä myös muutenkin vuolaasti kiittelee tietokantakoodaria siinä vaiheessa kun sitä erillisessä taulussa olevaa dataa täytyy käyttää johonkin muuhun tarkoitukseen tms.
 
Kannattaako yleensä MySQL tietokannan data jakaa useampaan tauluun, vai kasvattaa taulujen sarakkeiden määrää? Eli laitanko esimerkiksi asunnon osaketiedot(määrä, osakeryhmän alkuosa, loppuosa) omaan tauluun, joka liitetään asuntoon, vai suoraan asuntotauluun?

Karkea nyrkkisääntö on, että jos huomaat toistavasi tietoja eri riveillä ja se toisteisuus vähenee uudella taululla, niin ota uusi taulu käyttöön. Kannattaa miettiä, mihin muuhun dataa voisi tarvita tai laajentaa ja sen kannalta myös jakaa uusiin tauluihin.

Lähtökohtaisesti ensimmäisen osakkeen numero ja osakkeiden määrä voivat olla samassakin taulussa. Sitten voi miettiä, pitääkö varautua kahden asunnon ja osakkeiden yhdistämiseen tms. Tai millaisia hakuja pitää kantaan tehdä.
 
Vähän erinlainen kysymys, mitä täällä yleensä onkaan, mutta onko koodaamalla verkko oston mahdollisuuden(siis kortin liittäminen tiliin ostovälineeksi) ollenkaan mahdollista? Suunnittelemme ystävieni kanssa projektia, jossa olisi integroituna asiakkaan pankkikortti jolla voisi tehdä pienempiä ja suurempia ostoksia äpin sisällä.

Tällä hetkellä yhteydestä veloitettu hinta (paytrail, checkout finland ja stripe) ovat aivan liian kalliita 0,30-0,50 kertaosto hinnoillaan, koska välillä asiakkaalta laskutetut hinnat ovat kovin pieniä. Voiko ns. yhteyden luoda sinne pankkiin ihan omasta takaa koodaamalla?Löytyisiköhän tähän perehtyneen mielipidettä?

Kiitos jo etukäteen.
 
Vähän erinlainen kysymys, mitä täällä yleensä onkaan, mutta onko koodaamalla verkko oston mahdollisuuden(siis kortin liittäminen tiliin ostovälineeksi) ollenkaan mahdollista? Suunnittelemme ystävieni kanssa projektia, jossa olisi integroituna asiakkaan pankkikortti jolla voisi tehdä pienempiä ja suurempia ostoksia äpin sisällä.

Tällä hetkellä yhteydestä veloitettu hinta (paytrail, checkout finland ja stripe) ovat aivan liian kalliita 0,30-0,50 kertaosto hinnoillaan, koska välillä asiakkaalta laskutetut hinnat ovat kovin pieniä. Voiko ns. yhteyden luoda sinne pankkiin ihan omasta takaa koodaamalla?Löytyisiköhän tähän perehtyneen mielipidettä?

Kiitos jo etukäteen.
Onhan se mahdollista, mutta epäilen ettei rahallisesti kovin kannattavaa pienelle toimijalle.

Korttimaksu:
- Korttidatan käsittely (ja erityisesti tallentaminen) vaatii erinäköisiä lupia. Nämä luvat eivät ole ilmaisia ja vaativat jonkin sortin auditoinnin. Katso: Payment Card Industry Data Security Standard - Wikipedia
- Korttitransaktiot maksavat joka tapauksessa.
- Vaatii integroitumisen joka tapauksessa johonkin palveluun, joka ei varmasti ole ilmaista.

Verkkomaksu:
- Ei vaadi erityisiä lupia
- Sopimukset joka pankin kanssa erikseen. Hinnat riippuvat täysin näistä sopimuksista.
- Tekninen integraatio on helppo. Tuossa on valmis toteutus: GitHub - reaktor/maksunappi: A Node.js library for online payments in Finland.

Jos olisin itse perustamassa palvelua, jossa käyttäjät maksaisivat, niin ottaisin valmiin toteutuksen ja keskittyisin muihin asioihin kuin keksimään pyörää uudelleen.

PS. Jos kyse on mobiilisovelluksesta, niin Apple ei ainakaan hyväksy AppStoreen sovelluksia, jotka ohittavat heidän maksusysteemit in-app purchaseissa.
 
Näin semi-CLI-puristina fronttitaidot ovat täysin olemattomat, joten anteeksi jo etukäteen. Hieman apuja kaipaisin kuitenkin. Täytyisi rakennella GUI, jossa allekkain olevia elementtejä voisi järjestellä hiirellä vetämällä.

Esimerkki:

Koodi:
+-----------------------+
|      Elementti 1   ***|
+-----------------------+

+-----------------------+
|      Elementti 2   ***|
+-----------------------+

+-----------------------+
|      Elementti 3   ***|
+-----------------------+

Haluaisin siis tarttua hiirellä tuosta ***-kohdasta kiinni ja raahata Elementti 3:n E1 ja E2 väliin, jolloin elementtien järjestys vaihtuisi vastaavasti.

Koodi:
+-----------------------+
|      Elementti 1   ***|
+-----------------------+

+-----------------------+
|      Elementti 3   ***|
+-----------------------+

+-----------------------+
|      Elementti 2   ***|
+-----------------------+

Osaan kyllä googlettaa, mutta kun en oikein edes tiedä mitä etsin. :) Jos jotain vinkkiä joku viitsisi antaa niin pääsisin oikeaan suuntaan.
 
Näin semi-CLI-puristina fronttitaidot ovat täysin olemattomat, joten anteeksi jo etukäteen. Hieman apuja kaipaisin kuitenkin. Täytyisi rakennella GUI, jossa allekkain olevia elementtejä voisi järjestellä hiirellä vetämällä.

Tässä kait puhuttiin "fronttitaidoilla" viitaten web-teknologiohin, joten tässä yksi vastaus: Sortable. No jQuery.

Eli avainsanat googleen on "javascript" "sortable" tai "nestable" ja "list".
 
Pitäisi saada SSI:tä käyttäen yhteinen navigointipalkki monelle sivulle.

Kopioin toimivan navigointipalkin koodin tyhjään tiedostoon Notepad++:aan ja tallensin sen annetun ohjeen mukaan nimellä navbar.include. Sen jälkeen korvasin etusivun navigointipalkin koodilla <!--#include virtual="/hakemiston_sijainti/navbar.include"--> hakemiston sijainti luonnollisesti oikeana, mutta navigointipalkki ei tule enää sivulle.

Kokeilin myös navigointipalkin tallentamista html muodossa, eikä toiminut. Laitoin myös tuon navigointipalkin include-tiedoston samaan kansioon, missä HTML-tiedosto on ja SSI-koodiin hakemiston kohdalle pelkän "navbar.include", mutta ei toiminut sekään.

Millähän saisin tuon toimimaan? Netissä tulee vastaan juttua, että SSI on täysin vanhanaikainen, mutta annetusta ohjeesta ei tässä tehtävässä saa luistaa.

EDIT: Ongelma oli palvelimessa.
 
Viimeksi muokattu:
Moi, osaisikohan joku auttaa kun aiemmin tekemäni pieni loki-sovellus ei enää löydä tallentamiaan tiedostoja. Tämä tapahtui windowsin päivityksen (Fall Creators Update) asentamisen jälkeen. Sovellus toimi hyvin ennen sitä. Spoilerin sisältä löytyy aliohjelmat jotka hoitavat tiedostoon tallentamisen ja sen lukemisen. Kyseessä on siis UWP-ohjelma joka on tehty C# ja XAML-kielillä.

Tiedostot tallentuivat normaalisti tänne: C:\Users\Batman\AppData\Local\Packages\28bbc924-f8f6-454e-886a-10770f1e53d4_2sce9pbxsz1ej\LocalState

Ne olivat säilyneet siellä, mutta eivät näy sovelluksessa enää. Jos poistan tiedostot tuolta kansiosta ja luon uuden tiedoston ohjelmalla niin se näkyy ohjelmassa kunnes sen sulkee. Ohjelman uudelleen käynnistyksen jälkeen tiedosto ei enää näy ohjelmassa vaikka kansioon se kyllä tallentuu normaalisti.

Jos tarvitsette lisätietoja jostain, niin kysykää. Kiitos

Koodi:
 // TALLENTAA HELIKOPTERIT TIEDOSTOON
            private async void TallennaHelikopterit()
            {
                try
                {
                    // luo tiedoston
                    StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
                    StorageFile helikopteritTiedosto = await storageFolder.CreateFileAsync("helikopterit.dat", CreationCollisionOption.ReplaceExisting);

                    // tallenna tiedot tiedostoon
                    Stream stream = await helikopteritTiedosto.OpenStreamForWriteAsync();
                    DataContractSerializer serializer = new DataContractSerializer(typeof(ObservableCollection<Helikopteri>));
                    serializer.WriteObject(stream, Helikopterit);
                    await stream.FlushAsync();
                    stream.Dispose();
                }
                catch (Exception ex)
                {
                    Debug.WriteLine("Helikopterien tallennus epäonnistui." + ex.ToString());
                }
            }

            // LUKEE HELIKOPTERIT TIEDOSTOSTA
            public async void LueHelikopterit()
            {
                try
                {
                    // etsii tiedoston
                    StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
                    Stream stream = await storageFolder.OpenStreamForReadAsync("helikopterit.dat");

                    // lukee tiedot
                    DataContractSerializer serializer = new DataContractSerializer(typeof(ObservableCollection<Helikopteri>));
                    Helikopterit = (ObservableCollection<Helikopteri>)serializer.ReadObject(stream);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine("Helikopterien lukeminen epäonnistui." + ex.ToString());
                }
            }
        }
 
Moi, osaisikohan joku auttaa kun aiemmin tekemäni pieni loki-sovellus ei enää löydä tallentamiaan tiedostoja. Tämä tapahtui windowsin päivityksen (Fall Creators Update) asentamisen jälkeen. Sovellus toimi hyvin ennen sitä. Spoilerin sisältä löytyy aliohjelmat jotka hoitavat tiedostoon tallentamisen ja sen lukemisen. Kyseessä on siis UWP-ohjelma joka on tehty C# ja XAML-kielillä.

Tiedostot tallentuivat normaalisti tänne: C:\Users\Batman\AppData\Local\Packages\28bbc924-f8f6-454e-886a-10770f1e53d4_2sce9pbxsz1ej\LocalState

Ne olivat säilyneet siellä, mutta eivät näy sovelluksessa enää. Jos poistan tiedostot tuolta kansiosta ja luon uuden tiedoston ohjelmalla niin se näkyy ohjelmassa kunnes sen sulkee. Ohjelman uudelleen käynnistyksen jälkeen tiedosto ei enää näy ohjelmassa vaikka kansioon se kyllä tallentuu normaalisti.

Jos tarvitsette lisätietoja jostain, niin kysykää. Kiitos

Koodi:
 // TALLENTAA HELIKOPTERIT TIEDOSTOON
            private async void TallennaHelikopterit()
            {
                try
                {
                    // luo tiedoston
                    StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
                    StorageFile helikopteritTiedosto = await storageFolder.CreateFileAsync("helikopterit.dat", CreationCollisionOption.ReplaceExisting);

                    // tallenna tiedot tiedostoon
                    Stream stream = await helikopteritTiedosto.OpenStreamForWriteAsync();
                    DataContractSerializer serializer = new DataContractSerializer(typeof(ObservableCollection<Helikopteri>));
                    serializer.WriteObject(stream, Helikopterit);
                    await stream.FlushAsync();
                    stream.Dispose();
                }
                catch (Exception ex)
                {
                    Debug.WriteLine("Helikopterien tallennus epäonnistui." + ex.ToString());
                }
            }

            // LUKEE HELIKOPTERIT TIEDOSTOSTA
            public async void LueHelikopterit()
            {
                try
                {
                    // etsii tiedoston
                    StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
                    Stream stream = await storageFolder.OpenStreamForReadAsync("helikopterit.dat");

                    // lukee tiedot
                    DataContractSerializer serializer = new DataContractSerializer(typeof(ObservableCollection<Helikopteri>));
                    Helikopterit = (ObservableCollection<Helikopteri>)serializer.ReadObject(stream);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine("Helikopterien lukeminen epäonnistui." + ex.ToString());
                }
            }
        }
Saatko mitään virheilmoituksia? Exceptioninhan tuon pitäisi tulostaa.
 
Ajaako softa siis ihan alussa LueHelikopterit() ja ei palauta mitään virhettä? Voithan koittaa laittaa tuon debugin printtaan tuon storagefolderin lukemisen aikana.
Debug.WriteLine("Kansio:" + storageFolder.Name + " Polku:" + storageFolder.Path;
 
Saatko mitään virheilmoituksia? Exceptioninhan tuon pitäisi tulostaa.
Nyt kun kokeilin visual studiossa, niin ei tule mitään virheitä.

Ajaako softa siis ihan alussa LueHelikopterit() ja ei palauta mitään virhettä? Voithan koittaa laittaa tuon debugin printtaan tuon storagefolderin lukemisen aikana.
Debug.WriteLine("Kansio:" + storageFolder.Name + " Polku:" + storageFolder.Path;
Kyllä näin pitäisi olla ja ei tule virheitä.

Testaan tuota ehdotusta vielä myöhemmin paremmalla ajalla.

Huomasin sellaisen jutun, että jos valitsee Solution Configurations pudotusvalikosta Debug, niin ohjelma toimii normaalisti. Jos valitsee Release, niin silloin tiedostojen luku ei toimi. kts. kuva

nimetön.png


Onhan tämä nyt typerää kun ohjelma on ollut asennettuna koneelle puoli vuotta ja hyvin toimii, kunnes käyttöjärjestelmäpäivitys rikkoo sen näin. :(
 
No en tiedä mitä tuli sörkittyä, mutta nyt alkoi toimimaan. Asensin ohjelman useita kertoja uudelleen, mutta tuloksetta. Kuitenkin kun nyt testasin niin alkoi toimia jostain syystä. :btooth: Noh, hyvä näin.

Kiitoksia vain avusta kaikille :tup:
 
Tarkoitus olisi rakennella pieni tekstipohjainen käyttöliittymä, joka pyörisi suoraan Windowsin CMD:ssä. Alustavasti testailin tähän Javaa ja Lanternaa, mutta sillä tuo ei taidakaan onnistua (pyörii Swingin päällä). Millähän kielellä/kirjastolla tuo olisi Windowsissa mahdollista? Linux-puolella Python ja curses on tuttua, mutta tuo ei Windowsissa toimi.
 
Tarkoitus olisi rakennella pieni tekstipohjainen käyttöliittymä, joka pyörisi suoraan Windowsin CMD:ssä. Alustavasti testailin tähän Javaa ja Lanternaa, mutta sillä tuo ei taidakaan onnistua (pyörii Swingin päällä). Millähän kielellä/kirjastolla tuo olisi Windowsissa mahdollista? Linux-puolella Python ja curses on tuttua, mutta tuo ei Windowsissa toimi.
The Windows version of Python doesn’t include the curses module. A ported version called UniCurses is available. You could also try the Console module written by Fredrik Lundh, which doesn’t use the same API as curses but provides cursor-addressable text output and full support for mouse and keyboard input.
 
No huoh, olisihan tuo pitänyt itsekin löytää, mutta eipä osunut sitten millään silmään kun tuohon Lanternaan keskityin enemmän. Kiitos!
 
ohjelmointitaustaa on muutaman yliopistokurssin verran, kokemusta lähinnä javasta ja nyt tarkastelun alla C, joten melko alkutaipaleella ollaan. intoa kuitenkin löytyy.

omiin käyttötarpeisiin olisi hyödyllistä oppia lukemaan näyttöä ja sillä tapahtuvaa toimintaa, ja muodostaa niistä tekstimuotoinen tiedosto. esimerkkinä vuoropohjainen peli kuten shakki tai pokeri, lukea ruudulta mitä on tapahtunut (mitä nappulaa liikutettu tai mitä kortteja pöytään on tullut ts. mikä ruudulla on erilaista kuin hetki sitten) ja kirjoittaa se tiedostoon.

haluaisin vinkkejä materiaalista joilla opiskella ko. asiaa, en siis jo olemassa olevia ohjelmia kyseiseen ongelmaan. osaisiko joku osoittaa eteenpäin tällä tiellä?
 
ohjelmointitaustaa on muutaman yliopistokurssin verran, kokemusta lähinnä javasta ja nyt tarkastelun alla C, joten melko alkutaipaleella ollaan. intoa kuitenkin löytyy.

omiin käyttötarpeisiin olisi hyödyllistä oppia lukemaan näyttöä ja sillä tapahtuvaa toimintaa, ja muodostaa niistä tekstimuotoinen tiedosto. esimerkkinä vuoropohjainen peli kuten shakki tai pokeri, lukea ruudulta mitä on tapahtunut (mitä nappulaa liikutettu tai mitä kortteja pöytään on tullut ts. mikä ruudulla on erilaista kuin hetki sitten) ja kirjoittaa se tiedostoon.

haluaisin vinkkejä materiaalista joilla opiskella ko. asiaa, en siis jo olemassa olevia ohjelmia kyseiseen ongelmaan. osaisiko joku osoittaa eteenpäin tällä tiellä?
Noiden pelien kanssa toimimiseen olisi varmaan helpompiakin tapoja toimia, mutta jos ihan tosiaan haluat lukea tapahtumia koneen näytöltä, konenäkö (machine vision, computer vision) saattaa olla oikea hakusana. Samoin jonkinlainen kuvantunnistus (image recognition) voi varmaan auttaa. Suositulla TensorFlow-kirjastolla näyttää olevan opas jonkinlaiseen kuvantunnistukseen, joten siitäkin voi ehkä olla jotain apua. Enempää en valitettavasti osaa auttaa, koska minulta ei löydy aiheesta asiantuntemusta eikä tapahtuminen tunnistaminen koneen näytöltä ole todellakaan mikään triviaali tai edes helppo pulma ratkaistavaksi. Rajatut ratkaisut (esim. noihin tiettyihin peleihin rajatut) voivat toki olla järkevällä vaivalla toteutettavissa yksinkin.
 
ohjelmointitaustaa on muutaman yliopistokurssin verran, kokemusta lähinnä javasta ja nyt tarkastelun alla C, joten melko alkutaipaleella ollaan. intoa kuitenkin löytyy.

omiin käyttötarpeisiin olisi hyödyllistä oppia lukemaan näyttöä ja sillä tapahtuvaa toimintaa, ja muodostaa niistä tekstimuotoinen tiedosto. esimerkkinä vuoropohjainen peli kuten shakki tai pokeri, lukea ruudulta mitä on tapahtunut (mitä nappulaa liikutettu tai mitä kortteja pöytään on tullut ts. mikä ruudulla on erilaista kuin hetki sitten) ja kirjoittaa se tiedostoon.

haluaisin vinkkejä materiaalista joilla opiskella ko. asiaa, en siis jo olemassa olevia ohjelmia kyseiseen ongelmaan. osaisiko joku osoittaa eteenpäin tällä tiellä?
Jos haluat vain tehdä jonkin pelin, esim shakin niin siihen löytyy huomattavasti helpompiakin tapoja kuin lukea ruudulta mitä on tapahtunut, toki jos tarkoitus on opetella miten ruudulta luetaan se pelitilanne niin sitten antaa mennä vain.

Niin kuin tuossa jo mainittiinkin, kyseessä ei ole mikään ihan triviaali juttu mutta kyllä sen pitäisi onnistua jos jaksaa aihetta opiskella. Ei toki ensimmäiseksi projektiksi ehkä se helpoin.
 

Uusimmat viestit

Statistiikka

Viestiketjuista
261 802
Viestejä
4 547 686
Jäsenet
74 849
Uusin jäsen
ookooo

Hinta.fi

Back
Ylös Bottom