Zalogowany jako: gość

Forum

Wątek: Nowe API dla programów

Wróć do listy wątków

3 z 3

Poprzednia

41 z 59: zywek

Ja bym w sumie bardziej dla tego testu postarał się to jednak przerobić, żeby chociaż nie... BO to w sumie faktycznie może i do implementacji włąsnej. ALe np moznaby obracać samą broń.

16.12.2019 14:38

42 z 59: pajper

Implementacja Sapera w Elten API.
Program celowo napisałem na dwóch klasach. Jedna - Program_Saper - odpowiada za mechanikę gry, druga zaś - Struct_Saper_Board - za obsługę planszy.
Program wykorzystuje nowy sposób definiowania menu oraz map.
Ponownie wdzięczny jestem za wszelkie uwagi i propozycje i chętnie odpowiem na wszystkie pytania.
Warto zauważyć, że klasa Struct_Saper_Board może działać dla dowolnej wielkości planszy. Zasięg od A1 do J10 (100 pól) jest wpisany w kodzie na stałe, ale zmiana wartości 10,10 przy generowaniu planszy spowoduje zmianę pola gry.





class Program_Saper < Program
Name="Saper"
Version="1.0"
Author="pajper"
def main
menu=Menu.new {
option("New game") {
return start
}
option("Exit") {}
}
menu.open
finish
end
def start
@mines = input_text("How many mines?","numbers").to_i
if @mines > 20
alert("Too many mines, setting 20.")
@mines = 20
elsif @mines<3
alert("Too less mines, setting 3.")
@mines = 3
end
@board=Struct_Saper_Board.new(10,10,@mines)
game
end
def game
@lr=("a".."z").to_a
@ud=(1..@lr.size).to_a
@map=Map.new(@board.width,@board.height) {|m|
m.on(:move) {
t=@lr[m.x].to_s+@ud[m.y].to_s
s=@board.status(m.x,m.y)
if s==-1
play("list_checked")
elsif s!=nil
t+=": "+s.to_s
end
speak(t)
}
m.on(:key_escape) {
m.dispose
}
m.on(:key_enter) {
if @board.checked?(m.x,m.y)==false
o=@board.open(m.x,m.y)
if o==-1
play("explosion")
m.dispose
else
speak(o.to_s)
if @board.completed?
play("applause")
m.dispose
end
end
end
}
m.on(:key_space) {
s=@board.status(m.x,m.y)
if s==nil
play("list_checked")
@board.check(m.x,m.y)
elsif s==-1
play("list_unchecked")
@board.uncheck(m.x,m.y)
end
}
}
@map.trigger(:move)
@map.show
main
end
end

class Struct_Saper_Board
attr_reader :initialized, :mines
def initialize(x,y,mines)
@board= Array.new(x){Array.new(y)}
@tried=[]
@checked=[]
@mines=mines
@initialized=false
end
def width
return @board.size
end
def height
return @board[0].size
end
def make(startx,starty)
return if @initialized
@mines.times {
x,y=-1,-1
x,y=rand(width),rand(height) while x==-1||y==-1||((x-startx).abs<=1&&(y-starty).abs<=1)||@board[x][y]!=nil
@board[x][y]=-1
}
for i in 0...width
for j in 0...height
next if @board[i][j]==-1
c=0
for k in i-1..i+1
for l in j-1..j+1
next if k<0 or k>=width or l<0 or l>=height
c+=1 if @board[k][l]==-1
end
end
@board[i][j]=c
end
end
@initialized=true
end
def check(x,y)
@checked.push([x,y]) if !@checked.include?([x,y])
end
def uncheck(x,y)
@checked.delete([x,y])
end
def open(x,y)
@tried.push([x,y]) if !@tried.include?([x,y])
make(x,y) if !@initialized
return @board[x][y]
end
def opened?(x,y)
return @tried.include?([x,y])
end
def checked?(x,y)
return @checked.include?([x,y])
end
def status(x,y)
return -1 if checked?(x,y)
return nil if !opened?(x,y)
return @board[x][y]
end
def completed?
if (@tried.size+@mines)==(width*height)
return true
else
return false
end
end
end
#StandWithUkraine Shoot for the Moon. Even if you miss, you'll land among the stars.
16.12.2019 20:43

43 z 59: pajper

Chcę dodać proste API dla high scores. Problemem jest jednak otwartość Eltena i pisanych do niego programów. Umożliwiłoby to wpisanie dowolnego wyniku każdemu, kto rozczyta kod programu i wystuka odpowiednie polecenia w konsoli.
Oczywiście można kompilować odpowiednie rzeczy do bibliotek dll, ale EltenAPI miało być proste, a to na pewno do prostych spraw nie należy.
Pomysł jest więc taki, że każda aplikacja byłaby podpisywana odpowiednim certyfikatem uzyskiwanym z serwera. Kod uwierzytelniony takim podpisem może wysyłać dane na serwer. Gdy ktoś zmieni kod źródłowy programu, ten nadal będzie działał, ale jego zapytania dodawane do High Scores będą odrzucane.
Kod za to odpowiedzialny będzie kompilowany, ale nie ręcznie do aplikacji, a z góry dla Eltena.
W menu narzędzi pojawi się odpowiednia opcja podpisywania programów, która wygeneruje plik umieszczany w folderze aplikacji zawierający odpowiedni skrót i jego klucz.
Proces będzie taki:
W menu narzędzia mamy opcję generowania klucza dla programów. Wybieramy odpowiedni plik skryptu, na którego podstawie utworzony zostanie plik o rozszerzeniu eac.
Plik ten zawiera podpisany cyfrowo skrót kodu źródłowego aplikacji. Jednocześnie wygenerowany klucz RSA wysyłany jest na serwer.
Od tej pory pliki skryptów podpisywane tym kluczem mają dostęp do odpowiedniego API.

Interfejs OnlineDB jest bardzo prosty.

OnlineDB.load # zwraca tablicę wszystkich wyników
OnlineDB.push # dodaje wynik
OnlineDB.delete(index) # usuwa wynik

Baza może służyć nie tylko najlepszym wynikom, ale zapamiętywaniu stanów gry itp. itd. Można do niej zapisywać dowolne tablice i tablice haszowe, max. 8192 znaków na rekord. Dane przechowywane są w formacie JSON.

Ograniczeniem interfejsu jest wymieszanie danych, tj. jeśli gra zawiera kilka różnych tabeli, wszystkie są zachowywane w jednej strukturze OnlineTP i muszą być rozróżnialne odpowiednim polem, np. type.
Oznacza to, że przy wczytywaniu listy najlepszych wyników trzeba załadować i tak wszystkie stany gier itp. itd.
Celowo jednak nie tworzę funkcji działających na wielu tabelach, bo interfejs miał być z założenia prosty.
#StandWithUkraine Shoot for the Moon. Even if you miss, you'll land among the stars.
17.12.2019 00:18

44 z 59: pajper

Dla sygnałów o niskim priorytecie program może przekazać dane wraz z powiadomieniami "Co nowego". Powinno to dotyczyć sytuacji, gdy przekazanie informacji nie jest natychmiastowo konieczne. Sygnały te są odbierane co jedną do trzech sekund.
Jest to zatem metoda wystarczająca dla gier typu Szachy czy kościanych, gdzie oczekujemy na ruch przeciwnika, nie nada się jednak w dynamicznych grach multiplayer.
Do tych drugich służy interfejs socketów, o którym później, tj. jak go napiszę. :D Proste wysyłanie danych do agenta odbywa się poprzez funkcję send_packet(username, packet). Pakiet może być napisem, tablicą lub tablicą haszową.
Jeśli użytkownik ma otwarty w tym samym momencie ten sam program, w jego sesji wykonana zostanie funkcja on_packetreceived(packet).
Jeśli użytkownik nie ma uruchomionego programu, a jest to pierwszy pakiet od jego zamknięcia, pojawi się mu propozycja otwarcia aplikacji. Jeśli to zrobi, pakiet zostanie dostarczony.
Sample będzie w nowej implementacji Szachów.

Istnieje także funkcja notify_user(username,notification), która pozwala wysyłać powiadomienia.
Powiadomienia będą dostarczane tylko wtedy, gdy użytkownik-odbiorca ma także zainstalowaną daną aplikację.
#StandWithUkraine Shoot for the Moon. Even if you miss, you'll land among the stars.
17.12.2019 00:32

45 z 59: pajper

Gniazda user-user:
Za pośrednictwem serwera Eltena można zestawić bezpośrednie połączenie między komputerami użytkowników. Zestawienie to wykorzystuje protokół TCP. Użytkownicy są uwierzytelniani przez serwer, stąd też wiadomo, że do socketu podłączył się na pewno ten zaproszony.
Prosty interfejs serwer-klient pozwala na tworzenie zarówno sesji dwóch użytkowników, jak wielu więcej.

Uwaga!
Gry, które odbywają się turowo (szachy, karty, kości) lepiej jest wykonać na mechaniźmie OnlineDB, niż z użyciem gniazd. Dzięki temu będą dostępne w każdym momencie i nie będzie potrzeba łączenia się komputerów, a więc możliwe będzie kontynuowanie rozrywki nawet w interwałach czasowych.

Schemat połączenia:

srv = ElServer.new # tworzy instancję serwera
Zmienna srv posiada atrybut id (srv.id) oraz key (srv.key). Korzystając z nich, każdy może się do serwera przyłączyć:
sock=ElSocket.new
sock.connect(id, key)
Można jednak także zaprosić użytkownika:
srv.invite(username)

Po zaproszeniu użytkownika, pojawi się stosowne powiadomienie, a w Eltenie lub po jego przywróceniu z traya ujawni się zapytanie, czy osoba chce przyjąć zaproszenie do danego programu.

Kiedy użytkownik wybierze opcję Tak, wywołana zostanie funkcja programu
def self.event_elserver(sock)
# sock to gniazdo klienta, o tym zaraz
end

Na serwerze w tym momencie wykonane zostanie zdarzenie
srv.on(:connect) {|sock|
# sock to gniazdo klienta
}

Teraz już wysyłanie jest banalne. Korzystając z gniazd mamy do dyspozycji funkcje:
write(text) # wysyła napis
read(size) # czyta określoną ilość bajtów
avail # zwraca, ile bajtów pozostało do przeczytania

Może się wydawać skomplikowane, dlatego w następnym wpisie przedstawię prosty przykład programu.
#StandWithUkraine Shoot for the Moon. Even if you miss, you'll land among the stars.
22.12.2019 22:51

46 z 59: pajper

Program pozwala na zapraszanie użytkowników. Do każdego dołączonego użytkownika wysyłana jest wiadomość powitalna i informacja o każdym nowym użytkowniku.
Po otwarciu programu z zaproszenia, odczytywane są po prostu wszystkie wysyłane wiadomości.
Mam nadzieję, że przykład zilustruje sprawę.



class Program_ElSockExample
Name="ElSockExample"
Author="pajper"
Version="1.0"
def main
@srv=ElServer.new
@usersocks=[]
@srv.on(:connect) {|sock|
a="New user connected: #{sock.user}"
alert(a)
sock.write("Welcome on our happy server, there are #{@usersocks.size} users already connected.\n")
@usersocks.each {|u| u.write(a+"\n")}
@usersocks.push(sock)
}
menu=Menu.new {
option("Invite new user") {invite}
option("Exixt") {finish}
}
end
def invite
user=input_text("User to invite")
@srv.invite(user) if user_exists(user)
end
def self.elserver(sock)
alert("Connected.")
Timer.new(1,true) {
loop {
alert(sock.read(sock.avail)) if sock.avail>0
break if sock.closed?
}
}
end
end
#StandWithUkraine Shoot for the Moon. Even if you miss, you'll land among the stars.
22.12.2019 22:58

47 z 59: pajper

Możliwość szyfrowania kodu i plików programu. W menu narzędzia pojawi się odpowiedni kreatorek.
Mała uwaga z mojej strony. Pliki te będą deszyfrowane z jednego pliku do pamięci RAM. Jest to o tyle ważne, że gdy na przykład plik programu będzie miał rozmiar 128MB, jego ładowanie będzie po prostu bardzo długo trwało.
Dlatego ta funkcja powinna dotyczyć raczej małych dźwięków czy plików, do kilku-kilkunastu megabajtów. Jeśli komuś zależy na zaszyfrowaniu większych danych, liczonych w dziesiątkach lub setkach megabajtów, powinien użyć osobnych plików i stworzyć własny algorytm szyfrujący.
#StandWithUkraine Shoot for the Moon. Even if you miss, you'll land among the stars.
23.12.2019 12:08

48 z 59: pajper

Zkończyłem prace nad szkicem koncepcyjnym dla bazy danych aplikacji i postaram się ją jak najszybciej ukończyć, by pokazać efekt. Zasadniczo jest siedem takich baz pod klasą DB:
DB.private, DB.private_readonly, DB.protected, DB.protected_readonly, DB.public, DB.public_readonly i DB.shared . Każda z nich działa podobnie, z jednym wyjątkiem shared, ale o tym za chwilę.
Baza danych jest z perspektywy użytkownika tablicą, w której można normalnie zapisywać dane, przy czym przyjmowane są wyłącznie tablice, tablice haszowe i Stringi.

DB.public
#=> []

DB.public.push("To jest napis")

DB.public[0]
#=> "napis"


DB.public jest współdzielona dla całej aplikacji - każdy użytkownik może ją czytać, pisać do niej i ją edytować.

DB.private to baza prywatna użytkownika. Wpisy zapisywane w tej bazie są dostępne tylko dla niego. Może je usuwać, edytować i dodawać.
Pozwala ona zapisywać na serwerze różne postępy, stany czy co tam się chce.

DB.shared to baza współdzielona między użytkownikami. Usunięcie z niej danych usunie je tylko dla danego użytkownika.
Domyślnie nowy wpis w tej bazie jest widoczny tylko dla tego, kto go stworzył. Aby go udostępnić, należy wywołać

DB.shared.share(id, user)
Od tej pory w bazie DB.shared odpowiedni wpis się pojawi.

Nieco inaczej wygląda sprawa z bazą DB.protected. Ta jest bazą o ograniczonym dostępie.
Pisać do niej mogą tylko uwierzytelnieni klienci, innymi słowy baza ta wymaga podpisu cyfrowego programu, o tym pisałem wcześniej.
Oznacza to, że baza DB.protected działa jak DB.public z tym wyjątkiem, że jeśli ktoś zmieni coś w kodzie programu, przestanie być dostępna.


Ostatnie, co pozostaje, to bazy readonly. Działają one analogicznie do powyższych, ale po prostu...
można do nich zapisać dane, ale nie można ich potem usuwać ani edytować.


Jeśli są pytania lub uwagi, chętnie na nie odpowiem.
#StandWithUkraine Shoot for the Moon. Even if you miss, you'll land among the stars.
25.12.2019 23:17

49 z 59: pajper

Elten 2.4 będzie pozwalał na pisanie programów nie tylko w języku Ruby. Trwają prace nad udostępnieniem frameworków dla języka C# i Python, może w przyszłości pojawi się coś jeszcze.
Frameworki te będą dawały dostęp do wszystkich najważniejszych sekcji Eltena, a więc interfejsu użytkownika, baz danych aplikacji, sesji, gniazd P2P między użytkownikami, powiadomień itp.
Postaram się w ciągu miesiąca zaprezentować jakieś funkcjonalne demo.
#StandWithUkraine Shoot for the Moon. Even if you miss, you'll land among the stars.
13.06.2020 11:38

50 z 59: pajper

Przy okazji wprowadzenia programu Youtube, stworzyłem proste API do tłumaczeń programów. Mianowicie folder locale. :)
Pliki z tego folderu o nazwie języka: pl.mo, de.mo, fr.mo są automatycznie ładowane. I z tej przyczyny warto używać kontekstu - przy nachodzących na siebie tłumaczeniach, priorytet zawsze ma Elten.
Dostępne są standardowe funkcje Gettext, będzie przykład w dokumentacji.
#StandWithUkraine Shoot for the Moon. Even if you miss, you'll land among the stars.
13.06.2020 19:03

51 z 59: talpa171

I to jest bardzo dobra wiadomość! Szczególnie Python... Wielu sie ucieszy myślę... Taki to będzie, no... powiew nowoczesności. :D



--Cytat (pajper):
Elten 2.4 będzie pozwalał na pisanie programów nie tylko w języku Ruby. Trwają prace nad udostępnieniem frameworków dla języka C# i Python, może w przyszłości pojawi się coś jeszcze.
Frameworki te będą dawały dostęp do wszystkich najważniejszych sekcji Eltena, a więc interfejsu użytkownika, baz danych aplikacji, sesji, gniazd P2P między użytkownikami, powiadomień itp.
Postaram się w ciągu miesiąca zaprezentować jakieś funkcjonalne demo.

--Koniec cytatu

13.06.2020 19:45

52 z 59: zywek

Taak, pojawi się wiele nowości ode mnie, o ile oczywiście będę mógł sobie zainstalować każdy moduł pythona jaki się mi zamarzy.

13.06.2020 21:44

53 z 59: patrykkubaszczyk

O, Żywek będzie jakieś giery i programy skrobał.
Nie mogę się doczekać!
because I am now using mac as main comp, I will not come here too much.NEW
14.06.2020 12:15

54 z 59: daszekmdn

Jak będzie C# to i ja coś zamerdam.

14.06.2020 19:59

55 z 59: zywek

Pomagaj w rozwoju aplikacji mobilnej w xamarin

15.06.2020 21:04

56 z 59: daszekmdn

Nie znam na tyle programowania by pomagać w Eltenie.

15.06.2020 21:05

57 z 59: zywek

No to mamy interesujacą rzecz. Chcesz pisac programy w c# jk będzie api do tego a nie chcesz jednocześnie pomagać w rozwoju programu, choć prawdopodobnie będzie mobilk jednak w c#

15.06.2020 21:06

58 z 59: daszekmdn

Bo proste rzeczy w C mogę napisać, bo się dopiero ucze tego języka. Proste czy jeszcze dokładniej wyłozyć?

15.06.2020 21:11

59 z 59: zywek

Dokładniej.

11.01.2022 16:23

Wróć do listy wątków

3 z 3

Poprzednia

Nawigacja


Copyright (©) 2014-2024, Dawid Pieper