Moje projekty / OpenOffice.org2GoogleDocs / Bloggeroid / Gadacz / Chrome2Chrome / Kontakt ze mną   
Pokazywanie postów oznaczonych etykietą programowanie. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą programowanie. Pokaż wszystkie posty

niedziela, lipca 27, 2025

Case insensitive OS ma pewne problemy ;-)

Tak ogólnie to jestem wielkim zwolennikiem backward compatibility i seamless transition.

Czyli jak sam piszę soft to próbuję to robić tak, że będzie umiał pracować ze starymi formatami danych.
Ogólnie staram się to tak robić by istniała zawsze deterministyczna ścieżka transformacji. To się do pewnego stopnia da prawie zawsze zrobić.

System plików w macOS jest by default case insensitive, czyli plik README.md i readme.md są tym samym plikiem. Da się podobno system plików zmienić na case insensitive, ale wymaga to dziwnych operacji (jak reformatowanie dysku, bo jak OS jest OK z oboma przypadkami, to dysk by default jest sformatowany dla case insensitive).
To case insensitive jest jak rozumiem pozostałością po wcześniejszych OSach, najpewniej tym z Apple DOS z Apple II, który miał chyba tylko uppercase i tak zostało, więc system plików dla Classic MacOS stał się case insensitive i jak Classic MacOS stał się OS X (czyli de facto NextOS z Rosettą) to i system dla OS X dostał case insensitivity... OK, jest też wersja bardziej oficjalna, że Classic MacOS dostał ten ficzer specjalnie bo to było przyjazne dla userów... moje 20+ pracy z kodem sugerują, że to mogło być ubieranie w szatki ficzera czegoś co mogło wynikać np. z przeportowania kodu ;-) [ale fakt, to mogła być przemyślana decyzja, nie mająca nic wspólnego z tym, że kod dla Lisy był pisany na Apple II w Pascalu, czyli w języku który jest case insensitive i na OSie który wspierał tylko wielkie litery, a kod dla Classic MacOS był pisany na Lisa'ie....]
Zwykle to case insensitive nie robi problemów... chyba, że chcesz zrobić rename pliku z README.md do readme.md (czy jak w moim przypadku gdy przez pomyłkę miałem add.java i chciałem zmienić w Add.java).
Rename głupieje, bo każą mu zmienić nazwę pliku w już istniejącą nazwę....

Chociaż wydaje się, że twórcy narzędzi programistycznych, a może i samego OS mogliby wprowadzić zmiany w działaniu rename ;-) coś jak dodanie if'a który sprawdza, że hmm... nazwa pliku już istnieje i uchwyt do pliku to jest ten sam plik, ale jednak znak po znaku obie nazwy się różnią, więc trzeba pójść specjalną ścieżką... choć jak znam życie to ten przypadek też ma jakieś problemy, nie wiem, np. nie jest jednoznaczny przy konkurencyjnym dostępie do plików ;-) albo fanatyczny product owner powiedział "nie będziemy robić tej zmiany" ;-)



Podobne postybeta
Samsung nie umie w software ;-)
OOo2GD w różnych smakach ;-)
Lepsze formatowanie kodu w Obsidian'ie - trick
Trudne USB...
Docker image to taka kanapka ;-)

środa, lipca 16, 2025

Agent by Agent ;-) czyli o tworzeniu agenta AI agentem AI ;-)

Spróbowałem vibe coding z Gemini CLI.

Żeby było zabawnie poprosiłem je o napisanie mi czegoś podobnego do Gemini CLI, ale działającego z lokalnym modelem.

Myślałem o Codellama i Deepseek-r1, okazało się, że mniejsze modele z Codellama i Deepseek-r1 nie dawały w ogóle rady, ale już Codellama 34b, coś tam daje radę...

Zacząłem od prompta, który wytłumaczył, że chcę zbudować coś podobnego do Gemini CLI, ale z lokalnym modelem i że żeby dostać się do tego modelu to może używać kodu modułu mistral.py, który mu dałem. Wytłumaczyłem też, że powinien dodać do kodu fragmenty pozwalające na wykonywanie funkcji takich jak zapisanie pliku, przeczytanie pliku i uruchomienie komendy. Jako testu kazałem Gemini CLI instruować tworzonego agenta, że ma stworzyć plik z kodem w Pythonie, który stworzy program do liczenia Pi metodą Monte Carlo.

Zacząć działać, a ponieważ budowa agenta nie jest czymś co zostało oprogramowane już wiele razy to model, którego używa nie ma raczej duże wiedzy o tym...

Wygenerował kod i tu był pierwszy problem ;-) bo postanowił uruchomić agenta, ale jak go uruchomił to nie miał możliwości interakcji z nim ;-) bo przecież Gemini CLI to NPM i 1 wątek...

Przerwałem mu, wytłumaczyłem problem i zaproponowałem zrobienie wersji z serwerem HTTP, która będzie słuchać i odpowiadać, a on będzie mógł gadać do niej cUrlem...

Spodobało mu się, przepisał kod.

Uruchomił, wysłał cUrla i okazało się, że mu nie działa...

Zaczął debugować i z uporem maniaka prosił mnie o to żebym ręcznie włączył lub wyłączył serwer... wytłumaczyłem, że przecież sam to może robić... stwierdził, że fakt, i zaczął uruchamiać serwer w background (z &), a później killować go z pkill...

Problem był taki, że model zwracał kod, ale tworzony agent nie chciał go zapisać na dysk... czyli najpierw Gemini CLI kilka razy sam chciał ten kod zapisać do pliku, wyjaśniłem w końcu mu grzecznie, że oszukuje, że to ma zrobić agent.

Więc zaczął go poprawiać, uruchamiać, zabijać... uznał, że musi zrobić debug... tu miał masę problemów, jednym z nich było to, że znów żeby móc widzieć output serwera HTTP to musiał go uruchomić... ale w foreground, więc nie mógł wysłać cUrlem nic, bo wisiał ;-)

W końcu mu przerwałem i zaproponowałem, że może lepiej będzie użyć przekierowania do pliku, ba że może przecież przekierować do pliku output z serwera i z cUrla i porównać...

Sam też sprawdziłem kod i okazało się, że w prompt'cie tłumaczył modelowi, że ma komendy owijać w <<CMD>> </CMD>>, ale w kodzie szukał końcowego znacznika <</CMD>> więc go tam nie było...

W międzyczasie sam wymyślił, że lepiej od przekierowywania strumienia użyć biblioteki logging ;-)

Wypalił w trakcie całą pulę tokenów/requestów do lepszego modelu, przełączył się na gemini-2.5-flash i spalił 63% contextu.

W końcu zrobił jakąś pierwszą wersję agenta, która umie pisać na dysku i która stworzyła plik z kodem liczącym Pi metodą Monte Carlo, ale już uruchomić tego nie umiał... a w końcu chciał nadpisać plik "example content" ;-)

Często blokował się na czymś trywialnym i trzeba mu to było tłumaczyć jak "bardzo tępemu juniorowi", chociaż bardziej komuś kto niby kojarzy, że kod można pisać, ale jest pozbawiony jakichkolwiek zdolności do rozwiązywania problemów ;-)

Z tym, że parę lat temu nawet w to miejsce by nie można było dotrzeć ;-)



Podobne postybeta
Dowcipny laptop ;-)
[SOLVED :-)] Google kłamie ;-) co do tego jak często odświeża subskrypcję kalendarzy
Noblowisko
Strasząca książka - Extinction: The Thriller
System punktowania za publikacje w Policji...

środa, lutego 26, 2025

Życie artysty jest trudne - System Extensions na macOS z ARMem...

Artyście wszystko przeszkadza ;-)

Próbuję sobie zbudować dla macOS system plików z kompresją. Bo w pracy mam dużo JSONów.

I na moim "starym" Macbooku Pro z 2018 już śmiga połączenie Pythona z FUSE, nadal w wersji podstawowej, ale działa.
Żeby działalo na nowym Macu Mini z M4 Pro muszę włączyć System Extensions, a żeby je włączyć muszę wejść w jakiś specjalny tryb i mi się odechciewa... bo podejrzewam, że na firmowym laptopie nawet nie będę mógł ;-)
A czemu muszę włączyć System Extensions? Bo FUSE tak działa ;-)

A już miałem taki piękny plan, trzymanie struktury FSa w SQLite, 2 tabele jedna ze ścieżką do fstats, druga z path do offset i UID (który będzie od razu nazwą pliku) skompresowanego GZIPem czy czymś podobnym, jeszcze w tej tabeli info jakim algo kompresowane (bo może nie warto kompresować?).

Ale jak byłem na Gran Canarii to mi się nie chciało kodować, bo można było łazić, a teraz jak jestem w domu to mnie blokuje obawa przed włączaniem tych System Extensions ;-)

Życie artysty jest trudne ;p



Podobne postybeta
MJ
Prakacje z kodowaniem ;-)
Lutowe książki ;-)
"Semisubiektywna" klasyfikacja dokumentów ;-)
Macbook PRO Retina i OS X po 2* tygodniach

niedziela, lutego 02, 2025

Prakacje z kodowaniem ;-)

Jestem na prakacjach, więc wiadomo, że mój prywatny projekt się posuwa do przodu ;-)

Prakacje mają dużo słońca i takich tam:



Ale wieczoram siedzę i koduję i okazuje się, że mój pomysł na system plików dla macOS, który używa kompresji zaczął działać :-)

Jest straszliwie wolny, prędkość zapisu to na razie tak między 30 KB/s, a 1 MB/s ;-) ale to zrozumiałe, pierwsza wersja systemu zakłada po prostu, że każdy plik jest kompresowany w całości... co oznacza, że funkcje read i write, które czytają/zapisują tylko fragmenty pliku muszą ten plik za każdym razem rozpakować w całości, i w razie zapisu jeszcze raz go całego spakować.

Obecna wersja używa zwykłego systemu plików, zapisuje pliki pod zadanymi ścieżkami, jedyna różnica jest taka, że są one zZIPowane. 
Kolejna wersja powinna być miksem systemu plików i bazy w SQLite. Baza będzie służyła do trzymania struktury plików/katalogów i mapowania tychże do plików z danymi. Pliki będą dzielone na chunki po 8, czy 64 KB (jeszcze muszę zdecydować) i każdy plik będzie zapisywany w bazie tak, że będę tam miał offset i nazwę pliku z danymi... więc jak ktoś będzie chciał odczytać tylko kawałek pliku czy zapisać tylko kawałek pliku to nie będę musiał wszystkiego rozpakowywać, po prostu zrobię to na danym kawałku. A idea jest taka, że pliki danych będą odpowiadały chunkom, więc same powinny być mniejsze... do tego będę miał opcję dodania też obsługi sytuacji gdy po spakowaniu mam większy plik niż przed spakowaniem, wtedy dla każdego chunka mogę trzymać też "algo" użyte do kompresji i w razie czego trzymać raw data.

Naumiałem się, że FUSE ważne jest nie tylko open, ale i release ;-) bo bez tego szybko pojawia się błąd too many open files ;-)


Podobne postybeta
The Shepherd&amp;amp;#39;s Crown
Kod jako insight w umysł ;-)
Głupi macOS, głupi WebDAV, głupi ChatGPT ;-)
Życie artysty jest trudne - System Extensions na macOS z ARMem...
Robimy z telefonu/tabletu z Androidem serwer WebDAV ;-)

sobota, grudnia 07, 2024

Google mi wyłączyło kawałek jednego z API ;-)

Google mi zrobiło psikusa i wyłączyli API 2 dla Bloggera, tzn. przynajmniej jego część.

Przez to przestały działać 2 rzeczy,  mój programik który dodaje podobne posty do mojego bloga i Bloggeroid.

Na razie udało mi się lokalnie naprawić moje narzędzie do podobnych postów (nie mam pojęcia czy ktoś tego używa, ale to była fajna zabawa to pisać więc... ;-)), może zabiorę się też za Bloggeroida, chociaż tu będzie trudniej bo nawet jak zrobię nową wersję to nie wiem czy pamiętam hasło do klucza potrzebnego do podpisania, a do tego Google i tak mi skasowało chyba już konto developera ;-)

Ale też z przerażeniem odkrywam, że łatwiej mi wiele rzeczy pisać w Pythonie bo go częściej używam niż Java'y...

Ale wracając do API od Google, wygląda na to, że chociaż wszystko jest deprecated to jedyna rzecz, którą musiałem naprawdę przepisać to kod do pobierania ID bloga na podstawie jego adresu, reszta wydaje się działać, chociaż mam zamiar ją przepisać.
Zresztą mam dowód na to, że nie warto używać cudzego SDK... mój kod używa Data SDK od Google, ale żeby robić update do najnowszej wersji to musiałbym się z tym ścigać parę dni, a napisanie moich własnych implementacji kodu gadającego z Bloggerem zajmie mniej ;-)



Podobne postybeta
GUI, Swing i inne takie...
Dowcipny laptop ;-)
Papa dla ClientLogin
&quot;Medyczny&quot; dowcip dnia ;-)
Papa laptopku..... ;-)

sobota, września 21, 2024

Aplikacja w Java&#39;ie jako coś w czym można przeglądać pliki w macOS

Człowiek by myślał, że w zbudowaniu czegoś do wyświetlania plików największym problemem jest zrobienie samego wyświetlania, bo przecież coś takiego jak przekazanie pliku do narzędzia to pikuś.

Argumenty przekazywane do aplikacji to coś co wspiera chyba każdy język, więc naturalne byłoby użycie tego mechanizmu....

Ale nie, w macOS to zrobili inaczej ;-)

I jak chcesz popełnić apkę, która potrafi wyświetlić jakieś pliki (w naszym przykładzie txt) to trzeba zrobić parę rzeczy....

W kodzie trzeba powiedzieć, że chcielibyśmy przechwytywać otwieranie plików

Desktop.getDesktop().setOpenFileHandler(e -> {
System.out.println("File opened: "+e.getFiles().get(0).getAbsolutePath());
var file = e.getFiles().get(0);
var path = file.getAbsolutePath();

ale to za mało... bo jeszcze musimy powiedzieć o tym wyraźnie macOSowi plikiem Info.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>txt</string>
</array>
<key>CFBundleTypeName</key>
<string>Text File</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
</dict>
</array>
</dict>
</plist>
Kluczem jest podanie poprawnego typu plików.... niby txt jest dość oczywiste, ale wcześniej próbowałem to co sugerował Internet w osobie ChatGPT ;-) czyli public.plain-text...
Ale oczywiście plik Info.plist jakoś trzeba połączyć z naszym JARem....
I do tego służy jpackage:
jpackage --input <folderWithJAR> --name <NameOfApp> \
 --main-jar <nameOfJARfileInInputCatalog> \
--resource-dir <pathToFolderWiht_Info.plist>
To nam wyprodukuje plik dmg, którego możemy używać do instalowania aplikacji ;-) Na moim komputerze plik waży "niecałe" 56 MB ;-) a po instalacji apka waży jakieś 130-150 MB ;-)


Podobne postybeta
Z NMEA do KML (chyba najbardziej kryptyczny tytuł postu jak stworzyłem ;-))
Robimy widget do Windows 7 :-)
Niecne wykorzystanie refleksji... czyli jak poszukać tekstu w drzewie obiektów? ;-)
Jak walczyć z gigantycznym kodem w Java'ie, część 1 ;-)
Prosty spell checker, czyli jak umiejętnie połączyć teorie z praktyką

wtorek, września 17, 2024

Mały rant na macOS, Swifta i sandbox ;-)

Mam dużo pliczków tekstowych, różnych, a to logów, a to jakichś kawałków kodu i inne.

Na Windows dawno temu w TotalCommander robiłem F3 i było widać.

Jakoś nigdy nic fajnego nie znalazłem na macOS ;-) jest niby TextEdit, ale jest głupi jak but z lewej nogi. Np. trudno mi się czyta małe literki, to zwiększę... ale wtedy nie ma łamania linii, to zrobię wrap to page to mi zwinie na część ekranu, ale jak tam spróbuję zwiększyć czcionkę to zwiększa czcionkę w tym nieszczęsnym kawałku w który zwinął stronę...

To stwierdziłem, fajnie by było się nauczyć Swifta, to napiszę sobie prosty programik, przecież to nie może być trudne....

Ale kto by wpadł na to, że na macOS apka by default nie ma dostępu do plików? ;-) bo może działać tylko w sandboksie... tak jak na iOS...

No to próbuje w signing i podobnych dać jej dostęp do plików i podobno go ma, ale nadal nie umie czytać plików. To próbuję z startAccessingSecurityScopedResource, które w ogóle mnie nie pyta o nic, ot po prostu apka dostaje false i tyle.

Naprawdę się zastanawiam czy nie przejść do Java'y i Swinga, albo do JavaScript i Electrona ;-)

To tak w nawiązaniu do mojego postu sprzed paru tygodni, że dziś ktoś kto się uczy programować ma trudniej ;-)



Podobne postybeta
Teraz jest trudniej zacząć z programowaniem niż te 25-30 lat temu
Piesakrew!
Outlook zły
Java, JavaScript, Python, C++, C#? co ma przyszłość? 7 lat później ;-)
Pensje w IT są trudne

środa, sierpnia 28, 2024

Rube Goldberg machine do reminderów ;-)

Znów zbudowałem potwora ;-)

Jest tak, jestem bardzo chaotyczny, zwykle mi to nie przeszkadza bo mam na tyle dobrą pamięć i ogólny ogar, że w życiu moja chaotyczność mnie wiele nie kosztuje.

Ale bycie managerem ma swoje koszty. Naturalne jest, że zamiast pracować nad 1, 2 czy 3 rzeczami naraz, ale ze schodzeniem do detali bardziej się jest na poziomie, że w koło dzieje się kilkanaście czy kilkadziesiąt rzeczy i trzeba mniej więcej się w nich orientować...
Stąd potrzebuję czegoś do pamiętania o rzeczach do zrobienia, żeby nie przypominać sobie 2 dni później ;-)

Niby mam Todoista... mam nawet Worfklow w Alfredzie, który pozwala mi tworzyć taski w Todoist....

Ale Todoist nie ma powiadomień w normalnym planie i ogólnie jest dość ciężki. Ale Reminders w świecie Apple są całkiem fajne i się ładnie synchronizują między komputerami... no i ładnie się pokazują w macOS w obszarze powiadomień ;-)

I teraz mam kolejne Rube Goldberg machine ;-)

W Alfredzie piszę todo i dalej treść remindera.... mogę mu dodać czas, bo mam tego obsługę ;-)

Teraz jest sobie inny komputer, na którym w crontab jest kawałek Pythona który co 5 minut łączy się do API Todoista i pobiera taski.... jeśli task ma due date... to skrypt "pisze" skrypt dla osascript w którym tworzy reminder z daną treścią i danym due date... uruchamia ten skrypt... i zaznacza w Todoist taska jako Completed ;-)

Najistotniejszy kawałek kodu, ten który tworzy reminder wygląda tak:

def createReminder(text, dueDate):
current_time = dueDate.strftime("%d/%m/%Y %H:%M:%S")
text=unicodedata.normalize('NFC',text)

script = f'''
tell application "Reminders"
make new reminder with properties {{name:"{text}", due date:date "{current_time}"}}
end tell
'''
try:
print("==")
subprocess.run(["osascript", "-e", script])
print("Reminder created!")
except Exception as e:
print(f"Failed to create reminder: {e}")

jak widać, tworzy reminder używając AppleScript ;-)

Czy dałoby się to zrobić prościej?

Oczywiście ;-)

Ale taka budowa ma tą zaletę, że jest bardzo prosta :-) bo sklejam kawałki, które już mam napisane do innych rzeczy ;-)

Teraz po głowie mi chodzi coś co w momencie jak mi się zaczyna spotkanie w Kalendarzu z linkiem do spotkania na WebEx czy innym Zoomie to otwierałoby mi Apple'owe Notes na notatce, która by miała nazwę jak spotkanie z dopisaniem na górze pliku daty i czasu tego spotkania.... 
Taki sposób na zapamiętanie by robić sobie notatki ze spotkania....



Podobne postybeta
GPT + Python = sprawdzanie czy 5 książka z Bobiverse już jest dostępna ;-)
Kiedy skończyć pracę...
5 lat z macOS w domu ;-)
Żenienie Todoist z Obsidian przy pomocy Pythona ;-)
Rube Goldberg machine do panowania nad spotkaniami... częściowego chociaż ;-)

czwartek, czerwca 13, 2024

To działa!!! Wykryło mi dostępność Samertajm :-)

Od jakiegoś czasu (tak naprawdę od lutego ;-)) czekam na dostępną do pobrania wersję Samertajm, ostatniego (w sensie najnowszego) programu Abelarda Gizy.

Zapisałem się na listę z updatami, ale że nie ufam to zrobiłem sobie też swoje skrypty ;-)

Działają w domu i przed chwilą zobaczyłem coś takiego na moim iPhone'ie (OK, naprawdę to na iPadzie jak coś próbowałem rysować (spróbuj narysować propozycję możliwej ewolucji JSON schema'y ;-)):


Wlazłem na https://samertajm.pl/ i jest :-) tzn. będzie 19 czerwca :-)

I proszę, mój własny alert był szybszy niż czekanie na jakieś listy dystrybucyjne ;-)

Tak samo monitoruję kolejne książki S. H. Jucha i czekam tak samo (+ jeszcze używanie LLMa do czytania strony ;-)) na 5 książkę z Bobiverse :-)



Podobne postybeta
PayPal - rozczarowuje
Eventy na żywo nie zawsze są bardziej wow niż w TV ;-)
Jakie by tu zadanie zrobić? ;-)
Polowanie na Nexus 4 - wersja automagiczna ;-)
Luźne spostrzeżenia ;-)

poniedziałek, stycznia 22, 2024

Jak z metody size() w List w Java'ie dostać ujemną liczbę? ;-)

Chciałem dziś popsuć LinkedList, ale wychodzi na to, że mam za mało pamięci w komputerze ;-)

Popsucie miało wyglądać mniej więcej tak:

var list = new LinkedList<Integer>();
doMagic(list);
System.out.println(list.size()); // return negative number!!!

Gdzie doMagic miało wyglądać jakoś tak:

static void doMagic(LinkedList<Integer> l) {
for (var i=0L; i<Integer.MAX_VALUE+1000L; i++) {
l.add(Integer.valueOf(0));
}
}

No bo jeśli spojrzymy na implementację LinkedList to implementuje ona List, a List ma metodę size() która zwraca int, ale LinkedList nie ma ograniczenia na rozmiar innego niż pamięć, w samej metodzie linkLast(E e), która wołana jest z add(E e) mamy:

void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}

Co znaczy tyle, że jeśli mamy odpowiednio dużo pamięci to w pewnym momencie przekręcimy licznik ;-)

Czyli jakbyśmy zawołali size() to zwróci liczbę ujemną, ale jeśli policzymy wszystkie elementy kodem:

var count = 0L;
for (var n:list) {
count++;
}

To w count będziemy mieli 2147484647 ;-)
Co ciekawe zawołanie get(int) w takim przypadku wyrzuciłoby IndexOutOfBoundsException pokazując ujemną liczbę ;-)

Chyba znalazłem uzasadnienie dla kupienia Macbooka z M3 Max ;-) Bo chciałbym naprawdę sprawdzić czy to się tak zachowa ;-)

Inna sprawa ile byśmy potrzebowali RAMu żeby móc ten problem osiągnąć ;-) Tak jeden Node to powiedzmy między 48 a 64 bajty.... co daje dolną granicę najmniej 96 GB RAM ;-) ale podejrzewam, że tak naprawdę to by było jakieś 170 GB ;-)
Jeszcze chwilę potrwa nim będziemy mieli takie laptopy ;-) 
Największy Macbook Pro to teraz 128 GB RAM ;-)


[update]

I chyba nie muszę kupować takiej maszyny dużej ;-) bo nadal mogę ustawić rozmiar heapy na 150 GB ;-)

I wtedy gdy robię list.get(10) po dodaniu 2147484647 objektów to dostaję wyjątek:


A program w Activity Managerze ma 105 GB RAM przypisane ;-)

[next update ;-)]

Czyli wypisanie list.size() dało wynik -2147482649, ale już fragment:

var count = 0L;
for (var n:list) {
count++;
}

Nie zadziałał w ogóle, bo już w linii z for poleciał wyjątek ;-), okazuje się, że gdy jest produkowany iterator to wołany jest gdzieś w środku range check i ten wywala wyjątek dla Index: 0 ;-) 
Czyli LinkedList po przekręceniu licznika nie nadaje się nawet do iterowania ;-) ale co ciekawe można kasować elementy z przodu i tyłu aż nam wróci size do pozytywnych int'ów i można iterować ;-)



Podobne postybeta
Ile z obligacji... odsłona 2 ;-)
LinkedList w Java'ie to taki miś koala...
Po Devoxx&#39;ie
Ile w tym i przyszłym miesiącu z odsetek za obligacje?
Go dla Java'owca ;-) odcinek 2 "kontenery dwa ;-)"

czwartek, listopada 09, 2023

GZIP mi oddał 119 GB dysku ;-)

Gdy dziś zaczynałem dzień miałem 47 GB wolnego miejsca na dysku w firmowym Macbooku, teraz mam 166 GB ;-)

Odpaliłem mój skrypt, który tu już chyba kiedyś wrzucałem i zrobił porządki ;-)

Mam tak, że mam 1 katalog gdzie trzymam dużo danych w JSONie i lubię te dane mieć i nie chcę ich kasować, ale 1 kawałek danych to tak z 2-6 GB ;-)

No i potraktowanie tego GZIPem robi różnicę ;-)

Mój skrypt, który jakiś czas temu tu chyba wklejałem i który napisałem razem z ChatGPT wygląda tak ;-)

import os
import gzip
import concurrent.futures

def compress_file(file_path):
if not file_path.endswith('.gz'):
print(f"Compressing file {file_path}...")
with open(file_path, 'rb') as f_in:
with gzip.open(f"{file_path}.gz", 'wb') as f_out:
f_out.write(f_in.read())
os.remove(file_path)
else:
print(f"File {file_path} is already compressed in GZIP format and will not be compressed again.")

def compress_files_in_folder(path):
file_count = len([f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))])
if file_count > 500:
print(f"Compressing files in directory {path}...")
with concurrent.futures.ThreadPoolExecutor() as executor:
for filename in os.listdir(path):
file_path = os.path.join(path, filename)
executor.submit(compress_file, file_path)
else:
print(f"The number of files in directory {path} is less than 500.")

def process_folders():
root_path = os.getcwd()
with concurrent.futures.ThreadPoolExecutor() as executor:
for dirpath, dirnames, filenames in os.walk(root_path):
executor.submit(compress_files_in_folder, dirpath)

process_folders()

I działa tak, że po prostu idzie po podfolderach i jeśli jest tam więcej niż 500 plików to wszystkie z nich pakuje GZIPem... jeśli jeszcze nie są spakowane ;-)

Do tego mam bibliotekę w Pythonie do czytania danych i zamiast robić json.loads("\n".join(open(fname).readlines()) robię util.load(fname) ;-)




Podobne postybeta
GZIPem w plika z pomocą ChatGPT ;-)
Odzyskać trochę miejsca na dysku... w macOS ;-)
Jak zrobić plik OVPN (dla OpenVPN) w wersji unified format?
Żenienie Todoist z Obsidian przy pomocy Pythona ;-)
Mistral czeka na książkę

środa, listopada 01, 2023

GPT + Python = sprawdzanie czy 5 książka z Bobiverse już jest dostępna ;-)

OK, to do dziś raz dziennie uruchamiać się będzie na moim komputerze skrypt, który będzie wchodził na stronę autora Bobiverse i sprawdzał promptem do ChatGPT czy jest nowa książka czy nie ;-)

Prompt brzmi:

I have a status update snippet from an author's page. From this snippet, I need to know:
Whether the book mentioned is currently available for purchase.
The exact title of the book.
Any hint or specific date mentioned for the book's release.
Please provide the answers in JSON format like: {{ "bookAvailable": true/false, "bookTitle": "Title Here", "bookReleaseDate": "Date or Hint Here" }}.
Here's the snippet: {item}

Na "przed chwilą" odpowiedź była:

{
"bookAvailable": false,
"bookReleaseDate": "Hint of possible soonish recording",
"bookTitle": "The Bobiverse"
}

Teraz jeśli odpowiedź byłaby w bookAvailable na True... to skrypt odpali jeszcze jeden skrypt, tym razem w tym strasznym AppleScript od Apple ;-)

Skrypt wygląda tak:

tell application "Reminders"
make new reminder with properties {{name:{text}, due date:date "{current_time}"}}
end tell

I w razie się uruchomi doda Reminder, który mi się "przypomni" o 21 ;-)

W podobny sposób już mam informowanie mnie o spotkaniach przed 10 następnego dnia, oraz o nowych książkach Scota Jucha'y ;-)

Ciekawe było tworzenie tego prompta, bo najpierw go sprawdzałem z ChatGPT, jak już działał jak trzeba użyłem go "przeciwko" ;-) OpenAI API i GPT-3.5-Turbo i odpowiedzi nie były satysfakcjonujące, to dawałem prompt ChatGPT do przerobienia, ten przerabiał znów testowałem i krytykowałem wynik do ChatGPT ;-) w końcu ten prompt dobrze działał i dlatego go tutaj używam.

Tak w ogóle to patrząc na te LLM, to to jest ciekawa opcja, używać LLM do wyciągania jakiejś bardziej ustrukturyzowanej formy z tekstu czy czegoś podobnego i dalej pisać kod który używa tej ustrukturyzowanej formy.



Podobne postybeta
Mistral czeka na książkę
Rube Goldberg machine do reminderów ;-)
Search it later ;-)
Moc promptów
Kopia zapasowa ważna ;-)

wtorek, października 10, 2023

iPhone 15 Pro Max

To przyszedł nowy iPhone, od starego różni się tym, że jest lżejszy i ciut taki mniej kanciaty ;-) przez co lepiej w dłoni leży.

Ma też lepszy CPU, lepsze kamery i tak dalej.

Migracja poszła w miarę spoko, z wyjątkiem WhatsApp'a, którego całą historię czatów straciłem... bo nie pamiętałem hasła ;-), oraz aplikacji mBanku, która wszystko sobie przeniosła i uważała, że jest zarejestrowana, ale nie chciała działać, stąd trzeba ją było odinstalować i zainstalować od nowa i wszystko działa.

Teraz trzeba "starego" iPhone'a wyczyścić, tak samo jak i stary zegarek i przekazać dalej :-)

Z dużych plusów, jest USB-C :-)



Podobne postybeta
6:22 czyli środek nocy
Niezlecenia ;-)
Kilogram i ile to jest? To jest dopiero spór :-)
&quot;Praca cytatem&quot; - a fuj...
Nexus 4 - pierwsze wrażenia

sobota, października 07, 2023

Kopia zapasowa ważna ;-)

Zawsze i wszędzie piszą by zrobić kopię zapasową przed czymś ryzykownym....

Mam Ci ja sobie Todoista i Obsidiana i je kiedyś pożeniłem przy pomocy Pythona, do tego mam w Alfredzie wtyczkę która dodaje cosie do Todoista...

Mam więc takie coś:


W Alfredzie robię todo, które trafia do Todoist, a później mój skrypt robi mi taska w ToDo w Obsidianie...

Wpadłem na pomysł, że jeszcze fajnie by było dodać zapytanie do OpenAPI i ChatGPT z promptem:

Between triple backtics is item from my todo list it may be in English or Polish, if possible add some details like possible steps, sources and so on. Format text for "description" as markdown, and place it in JSON field "description".
Results should be JSON with original ToDo item as "title" and additional info as "description", if you are not able to do it return empty JSON. ```{item}```

I by zamienić mój flow w:



Nie było to jakieś przesadnie trudne...

Poza jednym małym problemem ;-)

W kodzie mojego skryptu chciałem się zabezpieczyć tak by skrypt nie pytał ChatGPT o rzeczy, które już mają jakieś dokumenty w Obsidian'ie...

Ale mi się źle warunek napisał, więc on pytał o te właśnie które już miały coś ;-)

Więc straciłem wszystkie własne notatki związane z moim ToDo...

Time Machine z macOS nie do końca chciało pomóc bo się ciągle wieszało, ale w końcu wejście na dysk z Time Machine i skopiowanie ręcznie plików pomogło ;-)



Podobne postybeta
Search it later ;-)
Żenienie Todoist z Obsidian przy pomocy Pythona ;-)
Rube Goldberg machine do reminderów ;-)
GPT + Python = sprawdzanie czy 5 książka z Bobiverse już jest dostępna ;-)
Mistral czeka na książkę

środa, września 27, 2023

Promptem w ToDo ;-)

W ramach inżynierii promptowej próbuję dziś użyć Barda i ChatGPT do przeprowadzenia krytyki mojego ToDo ;-)

Na razie prompt wygląda mniej więcej tak:

Poniżej jest lista rzeczy na moim ToDo, Twoim zadaniem jest skrytykować każdy z elementów, Twoja krytyka powinna opierać się na zadawaniu pytań, czy dana rzecz jest rzeczywiście potrzebna, na ocenianiu jasności elementu ToDo, oraz stwierdzać czy może istnieje znane rozwiązanie dla danej rzeczy.

Jeśli istnieją jakieś gotowe rozwiązania takie jak produkt, aplikacja, strona które oferuje daną funkcję podaj do nich linki, lub nazwy modeli.

Oto moje Todo:
<Todo>

Na razie działa to tak sobie, ale po dodanie po odpowiedzi kolejnego zdania: "w przypadkach gdy istnieją aplikacje lub urządzenia które wypełniają cele punktu w ToDo podaj ich nazwy i jeśli możliwe linki do nich."

ChatGPT zaczął nawet podawać jakieś linki, Bard nazwy aplikacji, ale tak bardziej generycznie.

Jeden z ToDo które mam brzmi:

  • jakaś apka na iPhone'a do ćwiczenia Tai-Chi
I odpowiedź z pierwszego prompta z ChatGPT to:
  • Czy sprawdziłeś już dostępne aplikacje, takie jak „Tai Chi for Beginners” czy „Tai Chi Step by Step”?
Z Barda:
  • Czy istnieje już taka aplikacja? Jeśli nie, to może warto ją stworzyć.
  • Aplikacja ta może być przydatna do nauki i ćwiczenia Tai-Chi. Może zawierać instrukcje, filmy i inne materiały pomocnicze.
Dla drugiego.

ChatGPT:
  • Tai Chi for Beginners (iOS)
  • Tai Chi Step by Step (iOS)
Bard:
  • Tai Chi for Beginners - aplikacja na iPhone'a, która zawiera instrukcje i filmy do nauki Tai-Chi.
  • Tai Chi Master - aplikacja na iPhone'a, która zawiera instrukcje, filmy i inne materiały do ćwiczenia Tai-Chi.
Nie jest jeszcze dobrze, ale wygląda to to obiecująco ;-)

Hmmm.... dodałem jeszcze jeden prompt ;-)
Dla każdego elementu z ToDo podaj 2 oceny (w skali od 1 do 7 gdzie 1 to najgorsza, a 7 najlepsza), pierwsza ocena dla sensowności/potrzeby, druga dla jasności celu

I tutaj nie ma zgody między Bardem i ChatGPT ;-)
ChatGPT uznał, że szukanie apki do Tai-Chi to 5/5, a Bard że 7/7.

Bard pokazał też wyniki w ślicznej tabelce :-)

Oba podały też słowne uzasadnienie dla swoich ocen.

Ale ogólnie się zgadzają, że np. taki cel na moim ToDo: "Coś do przeliczania Coli na kawy ;-)" to coś co nie jest zbyt sensowne (2 wg ChatGPT i 3 wg Barda bo uznał, że to może być zabawne), ale mają inne zdanie co do jasności celu (2 wg ChatGPT "Niejasne jest, do czego dokładnie ma służyć taki kalkulator." i 7 dla Barda.

Mam dostęp do API ChatGPT i właśnie mi świta pomysł na wtyczkę do Obsidiana... ale nie mam zbyt jasnych wymagań.


Podobne postybeta
Szybszy = lepszy?
Bard vs ChatGPT ;-)
Zaskakujący killer feature....
Przygotowywanie jajecznicy jako analogia procesu produkcji oprogramowania ;-)
Szczęśliwe nieszczęścia ;-)

poniedziałek, września 25, 2023

Prefix vs suffix dla ++ i --

Rozwiązywałem sobie dziś zadanie na LeetCode i mam tam teraz taką linię:

if (a[c-'a']--==0) return c;

chociaż wcześniej było:

if (a[c-'a']==0) return c;
a[c-'a']--

Ta wcześniejsza wersja mnie jednak ciut raziła więc zmieniłem w tą którą napisałem wcześniej.
Stwierdzam jednak, że wersja -- i ++ po zmiennej jest taka dziwna, bo trzeba się jednak wysilić by zrozumieć, że ta operacja wykona się dopiero po warunku. 

Nie zmienia to jednak faktu, że mam pewną słabość do tej pierwszej wersji ;-) Jakieś to takie bardziej kompaktowe jest.

Ciekawa sprawa bo np. w Elements of Programming Interviews in Java: The Insiders' Guide wszędzie używają gdy mogą wersji prefiksowej, zamiast sufiksowej bo wtedy ten kod który mam wyżej wyglądałby jak:

if (--a[c-'a']<0) return c;

i jakby się go czytało to by było "robimy dec na wartości tablicy dla danego znaku i jeśli jest mniejsza niż zero to zwracamy znak".

Ale tak się zastanawiam czy w kodzie produkcyjnym wypadałby użyć którejkolwiek z tych wersji innej niż 2, bo może i brzydka, ale wyraźnie widać co się dzieje.



Podobne postybeta
Zaczynam woleć Map&amp;amp;amp;lt;Key,int[]&amp;amp;amp;gt; nad Map&amp;amp;amp;lt;Key,Integer&amp;amp;amp;gt; ;-)
Olśnienia :-)
Autoboxing/Unboxing nie lubi sie z var - nadal ;-)
Google App Engine - pierwsze wrażenia
Kod jako insight w umysł ;-)