Protokol pro synchronizaci času se jmenuje NTP (Network Time Protocol) a na Linuxu se na to používá ntpd nebo chronyd (a nejspíš hafo dalších). Konfigurák je v /etc/{ntp,chrony}.conf. Takže v praxi bys použil některý z nich na klientech i serveru a na tom serveru bys pak použil vlastní zdroj času. A to už si asi můžeš udělat jak chceš, ale konkrétní zkušenost s implementací nemám.
Příspěvky odeslané z IP adresy 213.211.51.–
Já jsem zkusil vyhodit ten matplotlib. Jen jsem to na zkoušku namatlal a pořád to asi zbytečně pracuje s velkým obrázkem, který se jen pro zobrazení škáluje, ale litá to pěkně rychle.
To cv2 je jen binding 1:1 k té Céčkovské knihovně (cv) a v její dokumentaci je vždycky i signatura funkce v Pythonu a fungování je úplně stejné.
import cv2
import PIL.Image, PIL.ImageTk
import tkinter.filedialog
import tkinter as tk
def clamp(val, minval, maxval):
val = max(val, minval)
val = min(val, maxval)
return val
def remap_range(val, fromrange, torange):
frmin, frmax = fromrange
tomin, tomax = torange
frsize = frmax - frmin + 1
tosize = tomax - tomin + 1
delta = (val - frmin) / frsize
return tomin + tosize * delta
def fit_size(w1, h1, w2, h2):
scale = min(w2 / w1, h2 / h1)
return int(w1 * scale), int(h1 * scale)
class Box:
def __init__(self, x1, y1, x2, y2):
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
@property
def box(self):
return self.x1, self.y1, self.x2, self.y2
@property
def l(self):
return self.x1
@property
def r(self):
return self.x2
@property
def lr(self):
return self.x1, self.x2
@property
def t(self):
return self.y1
@property
def b(self):
return self.y2
@property
def tb(self):
return self.y1, self.y2
@property
def w(self):
return self.x2 - self.x1 + 1
@property
def h(self):
return self.y2 - self.y1 + 1
@property
def size(self):
return self.w, self.h
class RangeSlider(tk.Frame):
def __init__(self, master, valrange, valinit, *args, **kwargs):
tc = kwargs.pop("troughcolor", None)
super().__init__(master, *args, **kwargs)
self.valrange = valrange
self.lo = tk.Scale(
self,
from_=valrange[0],
to=valrange[1],
orient=tk.HORIZONTAL,
troughcolor=tc,
command=self._lo_changed,
)
self.hi = tk.Scale(
self,
from_=valrange[0],
to=valrange[1],
orient=tk.HORIZONTAL,
troughcolor=tc,
command=self._hi_changed,
)
self.vals = valinit
self.set(*self.vals, False)
self.lo.pack(fill=tk.X)
self.hi.pack(fill=tk.X)
self.on_change_callback = None
def on_change(self, callback):
self.on_change_callback = callback
def _lo_changed(self, value):
lo = int(value)
hi = max(lo, self.hi.get())
# change = (lo, hi) != self.vals
change = lo != self.vals[0]
self.set(lo, hi, False)
if change and self.on_change_callback:
self.on_change_callback(self, lo, hi)
def _hi_changed(self, value):
hi = int(value)
lo = min(hi, self.lo.get())
# change = (lo, hi) != self.vals
change = hi != self.vals[1]
self.set(lo, hi, False)
if change and self.on_change_callback:
self.on_change_callback(self, lo, hi)
def set(self, lo, hi, notify=True):
lo = clamp(lo, *self.valrange)
hi = clamp(hi, *self.valrange)
self.vals = (None, None) if notify else (lo, hi)
self.lo.set(lo)
self.hi.set(hi)
def get(self):
return self.lo.get(), self.hi.get()
class PixelPicker(tk.Canvas):
def __init__(self, master, image, *args, **kwargs):
super().__init__(
master, *args, **kwargs, bd=0, highlightthickness=0, cursor="tcross"
)
self.size = 0, 0
self.cimg = self.create_image(0, 0, anchor=tk.NW)
self.crect = self.create_rectangle(0, 0, 0, 0, dash=(10,), state="hidden")
self.image = image
self.sbox = Box(0, 0, *image.size)
self.vbox = None # prvni vykresleni bude v <Configure>
self.on_pick_callback = None
self.bind("<Configure>", self._on_resize)
self.bind("<Button-1>", self._on_pick)
self.bind("<Button-3>", self._on_zoom_selstart)
self.bind("<B3-Motion>", self._on_zoom_selupdate)
self.bind("<ButtonRelease-3>", self._on_zoom_selend)
self.bind("<Double-Button-3>", self._on_zoom_reset)
def set_image(self, image):
self.image = image
self.sbox = Box(0, 0, *image.size)
self.vbox = Box(0, 0, *fit_size(*self.sbox.size, *self.size))
self._show_image(self.image, self.sbox, self.vbox)
def on_pick(self, callback):
self.on_pick_callback = callback
def _show_image(self, image, sbox, vbox):
self.vimg = image.resize(vbox.size, PIL.Image.Resampling.NEAREST, sbox.box)
self.photo = PIL.ImageTk.PhotoImage(image=self.vimg)
self.itemconfigure(self.cimg, image=self.photo)
def _zoom_image(self, selbox):
if selbox.w < 5 or selbox.h < 5:
return
x1 = remap_range(selbox.l, self.vbox.lr, self.sbox.lr)
x2 = remap_range(selbox.r, self.vbox.lr, self.sbox.lr)
y1 = remap_range(selbox.t, self.vbox.tb, self.sbox.tb)
y2 = remap_range(selbox.b, self.vbox.tb, self.sbox.tb)
self.sbox = Box(x1, y1, x2, y2)
self.vbox = Box(0, 0, *fit_size(*selbox.size, *self.size))
self._show_image(self.image, self.sbox, self.vbox)
def _on_resize(self, event):
self.size = (event.width, event.height)
self.vbox = Box(0, 0, *fit_size(*self.sbox.size, *self.size))
self._show_image(self.image, self.sbox, self.vbox)
def _on_pick(self, event):
if self.on_pick_callback:
x = remap_range(event.x, self.vbox.lr, self.sbox.lr)
y = remap_range(event.y, self.vbox.tb, self.sbox.tb)
self.on_pick_callback(int(x), int(y))
def _on_zoom_selstart(self, event):
self.coords(self.crect, event.x, event.y, event.x, event.y)
self.itemconfigure(self.crect, state="normal")
def _on_zoom_selupdate(self, event):
x1, y1, _, _ = self.coords(self.crect)
self.coords(self.crect, x1, y1, event.x, event.y)
def _on_zoom_selend(self, event):
self.itemconfigure(self.crect, state="hidden")
x1, y1, x2, y2 = self.coords(self.crect)
x1 = clamp(x1, self.vbox.l, self.vbox.r)
x2 = clamp(x2, self.vbox.l, self.vbox.r)
y1 = clamp(y1, self.vbox.t, self.vbox.b)
y2 = clamp(y2, self.vbox.t, self.vbox.b)
self._zoom_image(Box(x1, y1, x2, y2))
def _on_zoom_reset(self, event):
self.set_image(self.image)
def main():
root = tk.Tk()
# filename = "pink-peony-148225487837A.jpg"
filename = tk.filedialog.askopenfilename(
filetypes=(
("Images", (".bmp", ".jpg", ".png")),
("All files", "*.*"),
)
)
if not filename:
return
image = cv2.cvtColor(cv2.imread(filename), cv2.COLOR_BGR2RGB)
image_r, image_g, image_b = cv2.split(image)
pil_image = PIL.Image.fromarray(image)
w, h = fit_size(*pil_image.size, 500, 500)
img_frame = tk.Frame(root)
im1 = PixelPicker(img_frame, pil_image, width=w, height=h)
im1.pack(side=tk.LEFT, expand=True, fill=tk.BOTH)
im2 = PixelPicker(img_frame, pil_image, width=w, height=h)
im2.pack(side=tk.LEFT, expand=True, fill=tk.BOTH)
img_frame.pack(expand=True, fill=tk.BOTH)
pixel_canvas = tk.Canvas(root, width=100, height=50, background="black")
pixel_canvas.pack()
rslider = RangeSlider(root, (0, 255), (10, 20), troughcolor="red")
rslider.pack(fill=tk.BOTH)
gslider = RangeSlider(root, (0, 255), (10, 20), troughcolor="green")
gslider.pack(fill=tk.BOTH)
bslider = RangeSlider(root, (0, 255), (10, 20), troughcolor="blue")
bslider.pack(fill=tk.BOTH)
mask_r = mask_g = mask_b = mask_full = masked = None
def update(slider, lo, hi):
nonlocal mask_r, mask_g, mask_b, mask_full, masked
# mask_r = mask_g = mask_b = mask_full = masked = None
if mask_r is None or slider is None or slider is rslider:
rl, rh = rslider.get()
mask_r = cv2.inRange(image_r, rl, rh, mask_r)
if mask_g is None or slider is None or slider is gslider:
gl, gh = gslider.get()
mask_g = cv2.inRange(image_g, gl, gh, mask_g)
if mask_b is None or slider is None or slider is bslider:
bl, bh = bslider.get()
mask_b = cv2.inRange(image_b, bl, bh, mask_b)
mask_full = cv2.bitwise_and(mask_r, mask_g, mask_full)
mask_full = cv2.bitwise_and(mask_full, mask_b, mask_full)
if masked is not None:
masked.fill(0)
masked = cv2.bitwise_and(image, image, masked, mask_full)
im2.set_image(PIL.Image.fromarray(masked))
def pixel_pick(x, y):
r, g, b = image[y, x]
rslider.set(r - 20, r + 20, False)
gslider.set(g - 20, g + 20, False)
bslider.set(b - 20, b + 20, False)
hex_rgb = "#%02X%02X%02X" % (r, g, b)
pixel_canvas.config(background=hex_rgb)
update(None, 0, 0)
im1.on_pick(pixel_pick)
for s in (rslider, gslider, bslider):
s.on_change(update)
root.mainloop()
if __name__ == "__main__":
main()
Ta funkce `pick_color`, když nastavuje ty slidery, tak každý vyvolá update, takže se to přepočítá třikrát.
Ten slider sám je zalagovaný i když nic nedělá, takže jeho ruční posunování je asi hlavně pocitově pomalé než, že by to nestíhalo. Ale možná to opravu nestíhá. Nevím jak ty události fungují, možná by pomohlo přidat test, jestli se hodnota těch sliderů změnila. (Protože teď ten update ignoruje ten parametr s hodnotou a počítá pro aktuální hodnoty, tak by tak možná šlo přeskočit nějaké staré eventy.)
Když se generují ty masky, tak to vždycky alokuje nové pole, ale ty funkce umožňují ukládat výsledek i do předalokovaného pole. A tak...
A celkově nakonec atualizace toho matplotu je asi poměrně pomalá. Klasika, funguje to tak, jak to je naprogramované.
No on zobrazí cokoliv, ale na to filtrování se mi zdá, že chceš něco složitějšího a to jsem myslel si pořešit sám a netrápit se s matplotem pro nic jiného než zobrazování.
import cv2
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.widgets import RangeSlider
import tkinter as tk
def main():
root = tk.Tk()
filename = tk.filedialog.askopenfilename(
filetypes=(
("Images", (".bmp", ".jpg", ".png")),
("All files", "*.*"),
)
)
if not filename:
return
image = cv2.cvtColor(cv2.imread(filename), cv2.COLOR_BGR2RGB)
image_r, image_g, image_b = cv2.split(image)
fig, (ax1, ax2) = plt.subplots(2, 1)
im1 = ax1.imshow(image)
im2 = ax2.imshow(image)
fig.subplots_adjust(bottom=0.30)
rslider_ax = fig.add_axes([0.20, 0.20, 0.60, 0.03])
rslider = RangeSlider(rslider_ax, "R", 0, 255, valinit=(0, 255))
gslider_ax = fig.add_axes([0.20, 0.15, 0.60, 0.03])
gslider = RangeSlider(gslider_ax, "G", 0, 255, valinit=(0, 255))
bslider_ax = fig.add_axes([0.20, 0.1, 0.60, 0.03])
bslider = RangeSlider(bslider_ax, "B", 0, 255, valinit=(0, 255))
fig_canvas = FigureCanvasTkAgg(fig, root)
fig_canvas.get_tk_widget().pack(expand=True, fill=tk.BOTH)
fig_toolbar = NavigationToolbar2Tk(fig_canvas, root, pack_toolbar=False)
fig_toolbar.pack(fill=tk.X)
def update(val):
rl, rh = rslider.val
gl, gh = gslider.val
bl, bh = bslider.val
mask_r = cv2.inRange(image_r, rl, rh)
mask_g = cv2.inRange(image_g, gl, gh)
mask_b = cv2.inRange(image_b, bl, bh)
mask = cv2.bitwise_and(cv2.bitwise_and(mask_r, mask_g), mask_b)
masked = cv2.bitwise_and(image, image, mask=mask)
im2.set_data(masked)
fig.canvas.draw_idle()
rslider.on_changed(update)
gslider.on_changed(update)
bslider.on_changed(update)
def pick_color(event):
if event.inaxes is not ax1:
return
x, y = int(event.xdata), int(event.ydata)
r, g, b = map(float, image[y, x])
rslider.set_val((r-20, r+20))
gslider.set_val((g-20, g+20))
bslider.set_val((b-20, b+20))
fig_canvas.mpl_connect("button_press_event", pick_color)
root.mainloop()
if __name__ == "__main__":
main()
Těch colorbarů můžeš mít několik a intuitivně bych řekl, že by velká část toho mohla jít implementovat čistě matplotem, ale nevím, já matplotlib, používám, jen když chci pěkné grafy a moc si ho nepřizpůsobuju. Ale samozřejmě zase si můžeš udělat nějaký slider bokem, který bude ten obrázek filtrovat přesně, jak chceš.
A ten gif jsem udělal jako nahrávku obrazovky/okna do klasického videa a pak až dodatečně zkonvertoval do gifu ffmpegem.
Nevím jak přesně je to implementované, ale v principu je to tak. Mimo vlastního okna, matplotlib ještě umožňuje ten plot vložit jako widget do vlastní aplikace a podporuje běžně používané toolkity, tady Tkinter.
Tkinter je GUI toolkit, labely, tlačítka a tak, to v Delphi nemusíš řešit externě. Matplotlib pro Delphi není. Ale Python samotný je snadno embedovatelný a to asi dělají tady: https://blogs.embarcadero.com/how-to-make-powerful-data-visualizations-with-matplotlib/#How_do_I_build_a_Delphi_GUI_for_the_Matplotlib_library
Změněné řádky jsou ty zakomentované s #old#
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
n_lines = 5
x = np.linspace(0, 10, 100)
y = np.sin(x[:, None] + np.pi * np.linspace(0, 1, n_lines))
c = np.arange(1, n_lines + 1)
#old# cmap = mpl.cm.get_cmap('jet', n_lines)
cmap = mpl.colormaps['jet'].resampled(n_lines)
fig, ax = plt.subplots(dpi=100)
dummie_cax = ax.scatter(c, c, c=c, cmap=cmap)
ax.cla()
for i, yi in enumerate(y.T):
ax.plot(x, yi, c=cmap(i))
#old# fig.colorbar(dummie_cax, ticks=c)
fig.colorbar(dummie_cax, ticks=c, ax=ax)
plt.show()
Na tom matplotu je pěkné, že poskytuje to zoomování a nemusíš to řešit sám. Ale nevím s čím zápasíš. Máš souřadnice, máš data a můžeš si s tím dělat co chceš :)
import cv2
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import tkinter as tk
def main():
root = tk.Tk()
filename = tk.filedialog.askopenfilename(
filetypes=(
("Images", (".bmp", ".jpg", ".png")),
("All files", "*.*"),
)
)
if not filename:
return
image = cv2.cvtColor(cv2.imread(filename), cv2.COLOR_BGR2RGB)
fig, ax = plt.subplots()
ax.imshow(image)
fig_canvas = FigureCanvasTkAgg(fig, root)
fig_canvas.get_tk_widget().pack(expand=True, fill=tk.BOTH)
fig_toolbar = NavigationToolbar2Tk(fig_canvas, root, pack_toolbar=False)
fig_toolbar.pack(fill=tk.X)
pixel_canvas = tk.Canvas(root, width=100, height=50, background="white")
pixel_canvas.pack()
pixel_label = tk.Label(root, text="RGB: ---\nHLS: ---")
pixel_label.pack()
doit_button = tk.Button(root, text="do stuff")
doit_button.pack()
def pick_color(event):
if event.button != 1 or event.xdata is None:
return
x, y = int(event.xdata), int(event.ydata)
rgb = image[y, x]
hls = cv2.cvtColor(image[y : y + 1, x : x + 1], cv2.COLOR_RGB2HLS)[0, 0]
hex_rgb = "#%02X%02X%02X" % tuple(rgb)
hex_hls = "#%02X%02X%02X" % tuple(hls)
pixel_canvas.config(background=hex_rgb)
pixel_label.config(text=f"RGB: {hex_rgb}\nHLS: {hex_hls}")
def do_stuff():
print("hello")
fig_canvas.mpl_connect("button_press_event", pick_color)
fig_canvas.mpl_connect("motion_notify_event", pick_color)
doit_button.config(command=do_stuff)
root.mainloop()
if __name__ == "__main__":
main()
#6 oxidián
Já jsem ten kód jen narychlo proletěl a moc jsem to nezkoumal. Chytil jsem se tohodle:
def do_job(self, event):
fig, ax = plt.subplots()
ax.imshow(self.large_image[self.selected_area[1]:, self.selected_area[0]:])
def pick_color(self, event):
x, y = int(event.xdata), int(event.ydata)
pixel_color = cv2.cvtColor(self.large_image[y:y+1, x:x+1], cv2.COLOR_BGR2RGB)[0,0]
A v tom se mi zdá, že by bylo ptřeba ty souřadnice přepočítat, nebo si uložit ten výřez:
def do_job(self, event):
fig, ax = plt.subplots()
self.zoomed_image = self.large_image[self.selected_area[1]:, self.selected_area[0]:]
ax.imshow(self.zoomed_image)
def pick_color(self, event):
x, y = int(event.xdata), int(event.ydata)
pixel_color = cv2.cvtColor(self.zoomed_image[y:y+1, x:x+1], cv2.COLOR_BGR2RGB)[0,0]
Ale teď koukám, že se to nikde nevolá a je to jen nějaký pozůstatek nabo halucinace ChatGPT.
Když používáš interní zoom toho matplotu, tak nemusíš řešit jestli je to zazoomované a přepočítavat souřadnice. Xdata a Ydata při tom kliknutí budou absolutní souřadnice.
Všude tam přistupuješ k tomu "large_image". Když v tom zoomu máš jen jeho výřez, tak souřadnice relativní k tomu výřezu musíš přepočítat na "globální" souřádnice v tom large_image.
Asi půjde získat data přímo z toho plotu, nebo si ulož ten výřez co v něm zobrazuješ a ber data z něj.
Teď mám zmatek v tom, co ti kde funguje :) Můžeš třeba zkusit na začátek programu přidat výpis verzí
import sys, pandas, sqlalchemy
print(sys.executable, pandas.__version__, sqlalchemy.__version__)
Jestli se ti to v různých prostředích liší. Ale ty logy tady vypadají, že tam máš stejné verze, tak v tom asi problém nebude a nenapadá mě kam se podívat, co by mohlo být špatně.
Co se týče toho selectu, tak do importu přidej "select" s malým s.
Do nedávna byl problém s tím, že pandas nefungovalo s novou verzí sqlalchemy, tak to zkus aktualizovat. (Jako bežný uživatel, ne root, ať si nerozhasíš systém, kdyby něco)
pip install --upgrade pandas sqlalchemy
Já jsem to teď zkoušel, jen jsem v tom readu za statement přidal ".selectable" a chodí mi to.
16.07.2022 JavaScript - http://programujte.com/forum/vlakno/194567-webova-aplikace-html-ccs-a-javascript/
23.07.2023 Python - http://programujte.com/forum/vlakno/194711-python-databaza/
30.07.2023 Java - http://programujte.com/forum/vlakno/194712-java-oop-konzolova-aplikace-evidence-pojisteni/
Možná je to nějaký rychlokurz postavený na samostudiu, ale není možné, abys nevěděl vůbec nic. Takže klasika, ostatní to nějak zvládnou, ale někteří na to dlabou.
Budu se opakovat:
- Je to tady počtvrté
- Opět jen zadání bez konkrétního problému
- Když to někdo udělá za tebe, tak je ti to k ničemu
- Nazdar
VARCHAR zabírá jen využitou délku + 1..2 byty na uložení té délky. Když nevíš takový základ, tak studium databáze přeskoč a vyber si podle screenshotů. Přidat kontrolu pozvánky před registrací by neměl být problém přidat kamkoliv.
První vytvoří set {None, None} (ve výsledku teda jen jeden {None}, protože je to set) a druhý vytvoří tuple (None, None).
(print vrací None)
#5 Mates
Dostaneš odpověď, jak udělat přesně to na co se ptáš a vyvodíš z toho, že to nejde...
Buď ty funkce nefungují, mně fungují, nebo vracejí něco jiného než čekáš, tak si tam přidej výpis návratové hodnoty.
Možná jsi ten kód napsal špatně, možná mačkáš špatnou klávesu, možná to spouštíš v IDE, kde přímé čtení kláves nefunguje. Těžko hádat.
Buď nekonečný cyklus nebo pád, těžko obojí. Na pád bych to neviděl a nekonečný cyklus je možný, pokud ukončovací podmínka nikdy nebude splněna. Tak bych se podíval, co máš v `x` po getch. Zdá se, že by to mohl být bajt a ne znak a pak by ta podmínka teda byla třeba `while x != b"p"`. Nevím, přidej tam print a podívej se.
Na to ve standardním Pythonu není úplně univerzální řešení.
Pokud jsi na Windows, tak bys měl mít dostupný modul "msvcrt", který tyto funkce má.
import msvcrt
...
if msvcrt.kbhit():
ch = msvcrt.getch()
Není mi jasné, co na tom obrázku má být vidět. Ty červené obdélníky? To neznamená chybu.
Aha, ty ses ptal na ten index :) To by taky šlo řešit v rewritech, ale můžeš prostě nastavit DirectoryIndex (ale je zvláštní, že to v něm teď nemáš)
DirectoryIndex index.php index.html ...
To co ti zachytil ten pattern je v $1 a na zachování parametrů je [QSA].
RewriteRule ^(.*)$ loxo/$1 [QSA,L]
Já to vidím stejně jako Jerry.
A na survey klikat nebudu.
Ty konverze na binární stringy jsou k ničemu, ale budiž...
Kóduj to po bajtech, ne po znacích, aby se ti to vešlo do těch 8 bitů.
Místo rjust dej ljust, protože s tím pak pracuješ jako big-endian intem, tak ať to zarovnání máš na konci.
Použij kratší bloky, nebo uprav generovaní klíčů pro větší.
def text_to_numeric_binary_blocks(self, text, block_size=8):
text = text.encode()
binary_blocks = [
''.join(format(byte, '08b') for byte in text[i:i + block_size]).ljust(block_size * 8, '0')
for i in range(0, len(text), block_size)
]
return binary_blocks
def numeric_to_text_binary_blocks(self, binary_blocks, block_size=8):
bytes_list = [int(block, 2).to_bytes(block_size, 'big') for block in binary_blocks]
text = b''.join(bytes_list).decode(errors='replace').rstrip("\x00")
return text
Před spojováním těch bloků musíš zajistit, aby všechny měly stejnou délku, jinak se ti je nepodaří správně rozdělit.
Ty konverze na inty a stringy jsou všechny blbě. Na implementaci samotného RSA můžeš použít inty, ale do ničeho jiného je nemíchej a zpracovávej to jako binární bloky.
Ten ".index" vrací pozici prvního výskytu. Musíš do toho zakomponovat to, že chceš další od posledního nalezeného.
Pravděpodobně k tomu dronu bude SDK přímo od výrobce. Tak projdi dokumentaci nebo jejich web.
Nemám ponětí.
Ionic poskytuje plný přístup k té databázi, takže si s ní můžeš dělat co chceš a v tom kurzu můžeš pokračovat.
Kdybys chtěl přejít na C# tak možnost je Xamarin (Forms nebo MAUI, nebo co všechno ještě mají).
Ale když úplně začínáš, tak si asi neber moc velké sousto a nejdřív se rozkoukej na něčem menším.
#43 Michal77
Jde, ale pak je potřeba hlídat, jestli to hlásí to Nb of scores and players doesnt match. Protože v tom případě tam ty špatně rozpoznané screenshoty budou chybět https://pastebin.com/hFcpNhAa
Jo, jsem tydýt, na zkoušení jsem si to omezil na jeden obrázek, ať to netrvá tak dlouho a zapomněl jsem to vyhodit. Tak tady https://pastebin.com/5Deny4Mc
Ne, napsal jsem to blbě. Tady je to komplet https://pastebin.com/51kUMBzf
To by šlo. Ten blok s "parsed_screenshot ... for ... nahraď takhle:
parsed_screenshot = []
for score, user in zip(scores, pl_s):
name1, name2 = "enemy", find_user(user[0]).name
if scores[i][1] > user[1]:
name1, name2 = name2, name1
parsed_screenshot.append([name1, score[0], name2])
Akorát to nemíchej. Buď všechna jména s původní verzí, nebo jen jeden team s touhle verzí.
V "processed_images" to vedle .png vytvoří ještě odpovídající .csv. A nejdřív bude samozřejmě potřeba doplnit obrázky pro jména všech zúčastněných.
JJ, pochopil jsi to správně. Já jsem tím vysvětlením myslel jestli chceš rozbor proč ti to nefunguje. K tomu bych jen řekl, že není potřeba vytvářet ten pár index-td, protože ten název už je v tom td.
Takže takhle třeba:
for td in mytds:
print(td.attrs["data-title"], td.text)
Jinak ta myšlenka není špatná, ale pak nebudeš procházet seznam, ale to mytds, který odkazuje na seznam:
for i, td in mytds:
print(seznam[i], td.text)
A pak ještě raději použití soup.find místo find_all a tím i list.append místo extend. (Když to td má být jen jedno, tak ať je to v tom kódu explicitně)
Chceš to vysvětlit, nebo jen rozchodit? :)
from bs4 import BeautifulSoup
import requests
url = 'https://www.in-pocasi.cz/aktualni-pocasi/olomouc/'
response = requests.get(url)
soup = BeautifulSoup(response.content, 'lxml')
seznam = ["Čas měření", "Teplota", "Vítr", "Vlhkost", "Tlak", "Srážky dnes", "Změna teploty (30 min)", "Teplota před 24 hodinami", "Rosný bod"]
data = {}
for title in seznam:
node = soup.find("td", {"data-title": title})
text = node.text if node else None
data[title] = text
print(data["Teplota"]) # přístup ke konkrétní hodnotě
for key, val in data.items(): # nebo průchod všech
print(f"{key}: {val}")
Nejspíš bude stačit někde vyhodit to sčítání :) Ukaž co máš a já na to mrknu.
Bavil jsem se s par kamarady co maji vice zkusenosti s programovanim. Vysledkem bylo, ze vsichni nenavidi jak tohle (ne)funguje a naprosty chaos kolem inicializaci.
To jste zajímavá parta důchodců :)
Kreslení na Form by mělo fungovat, ale neuchovává se a když se z nějakého důvodu překreslí, tak ty tvoje kresby zmizí. Teď kreslíš ještě před zobrazením formuláře a jeho zobrazení pak proběhne "normálně".
Hoď tam ještě PictureBox, jak psal Jerry, a kresli do jeho Image. To by mělo fungovat podle očekávání.
Používat na jednoduché kreslení přímo OpenGL, Direct3D nebo Vulkan je nesmysl. GLFW zjednoduše použití OpenGL, ale pořád je to OpenGL, z bláta do louže
SDL podobně, hodně low-level a samo o sobě nic moc neumí. Můžeš v něm přímo použít OpenGL nebo Direct3D, nebo všechno matlat "ručně" (nebo k tomu přidat ještě další knihovnu). Jestli chceš jen "hýbat texturama", tak bych asi taky doporučil SDL.
Použitelnější ve stylu té Watcomácké knihovny mi přijde Raylib. V tom smyslu, že vedle pokročilých funkcí, má i primitivní funkce pro kreslení čáry a kruhu a tak.
Když už spouštíš externí program, tak můžeš použít nějaký, který se na to hodí lépe. Třeba ImageMagick.
Jestli to chceš řešit posíláním kláves mspaintu, tak bych tam ještě přidal poslání příkazu k ukončení a pak neukončoval ten proces násilně, ale počkal až skončí sám (WaitForSingleObject nebo ten GetExitCodeProcess v cyklu).
Pravděpodobně to neděláš pro čísla s neomezeným rozsahem a používáš standardní typy C a pak maximální délku přece znáš.
Stylová výhrada - ověření toho hesla udělej hned na začátku. Takhle vždycky "vykresluješ" ten přihlašovací formulář a při správném hesle ho pak "zahodíš".
A to je nejspíš i důvod proč to nefunguje. V odpovědi od serveru jsou takzvané hlavičky a za nimi pak tělo dokumentu. Ty vypíšeš ten přihlašovací formulář (dokument) a potom už je pozdě přidávat hlavičky (funkce header). Server může být nastavený tak, že data neodesílá hned a můžeš hlavičký nastavovat "dodatečně", ale pokud tak nastavený není, tak to nebude fungovat.
Jiný problém tam nevidím.
- Je to tady potřetí
- Opět jen zadání bez konkrétního problému
- Když to někdo udělá za tebe, tak je ti to k ničemu
- Nazdar
Ano, v Javě (možná bych v dnešní době zkusil spíš C#) by to šlo bez nutnosti čehokoliv dalšího. Jako editor můžeš zkusit třeba NetBeans, kde si to okno můžeš vizálně naklikat.
Předpokládám, že jsi ten systém měl funkční a až instalací python3-tk se něco rozbilo. Tak ten rozhodně odinstaluj (apt remove). Z hlavy nevím na co s to ptá, ale vyber tak ať potvrdíš odstranění.
Celkově je problém v tom, že ten systém máš poměrně starý. Takže třeba máš nějaký balíček ve verzi 0.1 a pokouší se aktualizovat na 0.2, ale v repozitářích už je jen 0.3. Kouknul jsem na některé ty chyby a požadované verze jsou pořád na old.kali.org.
Takže v souboru /etc/apt/sources.list teď máš řádek s http.kali.org. To změň na old.kali.org. A pak dej zase apt update/dist-upgrade (nebo celý ten odstavec příkazů, jak jsem ho napsal předtím). Klidně několikrát, dokud to něco instaluje. Težko říct v jakém stavu to teď máš, ale měl by ses tak dostat na starší, ale funkční verzi.
Pak můžeš zkusit zase přepsat old.kali.org na http.kali.org a znova aktualizovat, ale asi pořád budeš tak pozadu, že to neprojde. Takže tam asi rovnou nech old. Doinstaluj ten Tkinter a pokračuj v tom, co jsi chtěl dělat.
A pak někdy až budeš mít chuť, tak to úplně přeinstaluj. A celkově když jsi na "rolling" verzi nějakého systému, tak je potřeba často aktualizovat.
To vypadá, že se ti Tkinter nainstaloval, ale jen nějak částečně kvůli tomu problému se závislostmi.
Pokud používáš snapshoty, tak se nejdříve ujisti, že máš správně datum/čas (a ne třeba týden starý snapshot).
A pak zkus tohle, něco z toho by se mělo chytnout. Nevím, jestli se v Kali ten balíček jmenuje python3-tk, kdyžtak to změň.
sudo apt-get remove --purge python3-tk
sudo apt-get clean
sudo apt-get update
sudo apt-get --fix-missing update
sudo apt-get --fix-broken install
sudo dpkg --configure -a
sudo apt-get update
sudo apt-get dist-upgrade
# pokud to ^^ pořád hlásí chyby, tak celý ten odstavec projeď ještě jednou
sudo apt-get install python3-tk
Access asi neumí CASE-WHEN. Můžeš použít IIF nebo Switch.
Ta metoda je statická, takže nemá přístup k instanci toho formuláře s tím editem.
Težko říct, jak to používáš, ale pravděpodobně ji nepotřebuješ mít statickou. A pokud jo, tak jí tu MAC předej třeba parametrem.
Driver psát nemusíš. Obzvlášť když Widle to zařízení vidí.
Pracovat s těmi kartami pak můžeš přes SC API.
Konkrétně pro .NET nevím, ale existuje Windows.Devices.SmartCards a živý je i projekt pcsc-sharp. Nebo můžeš použít SC API přes P/Invoke.
Těžko takhle hádat. Buď řádně doběhne nebo spadne, kvůli nějaké chybě.
Ukaž kód a/nebo chybový výpis.
Na začátek přidej uses math; tim se ti zpřístupní ty matematické funkce. A Pascal asi nemá operátor ^. Místo x^2 můžeš zkusit x**2 nebo prostě x*x.
Tak popiš, jak si představuješ ten rozložený výsledek a já ti napíšu, jak ho složit dohromady.
class AA:
...
class AB:
...
class AC:
...
class A(AA, AB, AC):
...
Napiš, co je původní záměr a vymyslíme řešení, které není takový nesmysl.
V první řadě u všech funkcí, které mohou vrátit chybu, přidej kontrolu chyb.
V tom kernelu se mi nějak nepozdává to result++, jakože ++ na floatu. Tipuju, že se to ani nezkompiluje, ale jistý si nejsem.
Netuším proč máš global dvouhodnotový, ale když to tak máš, tak obě hodnoty inicializuj.
A a B nejdřív inicializuješ mallocem, ale pak je nastavíš na adresu lokálních proměnných, takže free na konci nejspíš sletí.
Nekonečný cyklus tam nevidím, ale zjevně je to dvouminutová matlanina a osobně nemám chuť to zkoumat.
Vývoj Windows vůbec nesleduju a možná už jsou lepší způsoby, ale v principu, když se ten tvůj program spustí, tak můžeš detekovat, jestli jiná instance už běží a jen jí poslat požadavek o provedení té akce.
Používá(-val) se na to Mailslot, Named Pipe, Socket... (viz MSDN) Takže něco z toho vytvoříš a čekáš na zprávy. Když se to vytvořit nepodaří, tak nejsi první a jen pošleš zprávu a skončíš.
Nebo okenní zprávy. Vylistuješ seznam oken a podle titulku nebo souvisejícího exáče detekuješ, jestli patří tvému programu. A když jo, tak tomu oknu pošleš zprávu (PostMessage). To bude možná jednodušší.
Samořejmě by nebylo od věci dělat ptákoviny mimo transakci, ale jo, to je její pointa - začneš transakci, pak uděláš X příkazů a nakonec změny uložíš nebo zrušíš.
Tomu se říká transakce. Buď se udělá všechno nebo nic.
https://dev.mysql.com/doc/refman/8.0/en/sql-transactional-statements.html
Myslím, že to trénování nemusíš dělat a můžeš použít předtrénovaný model (nejspíš proto na ten problém ostatní nenarazili).
Ale pokud chceš, tak můžeš upravit ten if v args.py.
- if args.p_dataset_config is not None:
+ if hasattr(args, "p_dataset_config"):
$('label[for="sendNewsletter"]').contents()[1].textContent = 'nazdar';
Ech, když ti jiný kód na stejné adrese funguje, tak to nebude mono režimem. Čtu strašně nepozorně :) Takže asi ty indexy.
#34 Martin
Jejda, ty jsi ale drsňák.
To vidím jak to dokázali napsat, když neví ani příkaz na vymazání prostředí
U všech tvých dotazů je jasné, že všichni zúčastnění by to měli za pár minut. Konkrétní kód ti do teď nikdo nenapsal, protože na to dlabeš a "udělejte za mě" moc nefunguje.
DOSbox nešel spustit, protože nebyl povolený virtuál v biosu a ani ve windowsu, není můj problém, že tomu nerozumíš, nebo nechápeš, ale je to bohužel tak, nefungovalo mi to předtím a teďka jo.
DOSBox virtualizaci nepoužívá a nepotřebuje, tudíž ji není potřeba zapínat. To by ses ale musel obtěžovat to zkusit a nevymýšlet si.
Jde vidět, že nic moc nevíš jak tady vidím hnedka co píšeš za nesmysly. Musel jsem aji vysvětlovat zadání, jde vidět že si jen tady hraješ na borce, přitom vůbec nic nevíš no. Vtipní tito lidé :)
Zadání jsi musel vysvětlovat, protože jsi ho napsal debilně. Já jsem tě prokoukl rychle, ale Jerry s tebou ztrácí čas a dokonce ti fotí knížku, tak se chovej uctivě, zmrde.
Virtuál nepotřebuješ. Rozchodit DOSBox je záležitost minuty, jak už psal Jerry.
A jestli to použiješ, tak do té sekce Service asi ještě přidej User=... a Group=... pod kterými to má běžet.
Od PHP jako takového bych problém nečekal a ta knihovna pro MQTT vypadá dobře, takže když preferuješ PHP, tak bych se nebál to zkusit. Kdyžtak můžeš třeba pro jistotu po každých 1000 zprávách ten skript ukončit.
Na tom Debianu ti pravděpodobně beží systemd, tak [re]start můžeš řešit přes něj.
/etc/systemd/system/zigbeemqtt.service
[Unit]
Description=zigbeemqtt
After=network-online.target
Wants=network-online.target systemd-networkd-wait-online.service
StartLimitIntervalSec=300
StartLimitBurst=5
[Service]
ExecStart=/foo/bar baz
Restart=on-failure
RestartSec=1s
[Install]
WantedBy=multi-user.target
Jestli tou analýzou myslíš kontrolu nebo doplňování interpunkce, tak češtinu prostě nejde strojově analyzovat pro jednoznačné pochopení významu a bez toho nejde (stoprocentně) opravovat interpunkci. Link nemám, ale když nad tím budeš koumat, tak tě určitě pár přikladů napadne.
Natrénování toho, čemu se dneska říká AI (která neví, ale dost dobře hádá) taky nevidím nadějně.
RLC/RRC rotuje přes carry flag. Tzn. že jak se ty bity posunují, tak se ten jeden krajní vyšoupne do carry a ten na druhé straně zase doplní z předchozí hodnoty carry. To nechceš.
Zkrátka místo RLC/RRC použij RL/RR.
Jinak tam nic vyloženě špatně nevidím. Kromě toho, že to není dokončené.
rd.nextInt(limit);
A co nevíš?
Tak mě napadá, že už při načítání můžeš ukládat jen půlku řádku a rovnou s tím ukončovačem. Tím se to dost zjednoduší.
OK, u té funkce 0x0A je v tom bufferu 1 byte určující kapacitu, pak 1 byte určující délku načtených dat, a pak X byte těch dat.
Nevím, jak s touhle funkcí zjistit konec vstupu. Asi ji používáte tak budeš vědět, jak to děláte.
To, že rovnou máš v paměti [delka, data...] se hodí a použil bych to pro uložení všech řádků. Takže nakonec můžeš mít kompletní data ve formátu:
3, 'abc', 6, 'nazdar', 5, 'bazar'
Ty řetězce pak projdeš a před výpisem doprostřed vložíš ten ukončovací '$' pro funkci 0x09.
V pseudokódu celý program může vypadat nějak takhle:
max_line_count equ 600
max_line_len equ 100
segment code
start:
...
read_lines:
if line_count == max_line_count
goto print_lines
; nacteni radku
buffer.used = 0
int21.read(buffer)
; nevim jak s touto funkci detekovat konec vstupu
; dejme tomu, ze to bude zadani <ctrl-z>, <enter>
; tj. v bufferu bude jeden znak s hodnotu 26
if buffer.used == 1 and buffer.data[0] == 26:
goto print_lines
; ulozeni radku. delka + data
copy_src = @buffer.used
copy_dst = save.ptr
copy_len = buffer.used + 1
copy(copy_dst, copy_src, copy_len)
line_count += 1
save.ptr += copy_len
goto read_lines
; vypsat prvni polovinu nactenych radku
; a z kazdeho radku jen prvni polovinu nactenych bajtu
print_lines:
line_count = line_count / 2
save.ptr = @save.data
next_line:
if line_count == 0
goto end
line_count -= 1
line_length = save.ptr[0]
line_data = save.ptr + 1
save.ptr += 1 + line_length
line_length = line_length / 2
if line_length == 0
goto end_line
line_data[line_length] = '$'
int21.print(line_data)
end_line:
int21.print(crlf)
goto next_line
end:
int21.exit(0)
segment data
line_count dw 0
crlf db 13, 10, '$'
buffer:
.max db max_line_len + 1
.used db 0
.data resb max_line_len + 1
save:
.data resb (1 + max_line_len + 1) * max_line_count
.ptr dw save.data
Pokud to nemusí běžet na DOS 1, tak s funkcemi 0x3F/0x40 to podle mě bude jednodušší.
Tak v první řadě pro funkci 0x0a musí být v tom bufferu jeho délka, a pro funkci 0x09 musí být ten řetězec ukončený dolarem.
To je zvláštní, že to nemá tu definici Fields, ale toto teda (u mě) chodí.
from pdfrw import PdfReader, PdfWriter, PdfDict, PdfName, PdfString
def merge(outfile, seznam):
writer = PdfWriter()
merged_acroform = None
for idx, fname in enumerate(seznam):
reader = PdfReader(fname)
assert not reader.Root.AcroForm or not reader.Root.AcroForm.Fields
if merged_acroform is None and reader.Root.AcroForm:
merged_acroform = reader.Root.AcroForm
for page in reader.pages:
for annot in page.Annots or []:
name = annot.T[1:-1]
annot.T = f"{name}_merge{idx}"
writer.addpages(reader.pages)
if merged_acroform:
writer.trailer.Root.AcroForm = merged_acroform
else:
writer.trailer.Root.AcroForm = PdfDict({PdfName("NeedAppearances"): PdfString("true")})
writer.write(outfile)
Jestli můžeš, tak pošli 2 ukázkové soubory. Já na to mrknu.
Mně funguje zopakování a přejmenování definice polí. (Merguju stejné formuláře)
from pdfrw import PdfReader, PdfWriter, PdfName
def merge(outfile, seznam):
PdfT = PdfName("T")
PdfFields = PdfName("Fields")
writer = PdfWriter()
merged_acroform = None
for idx, fname in enumerate(seznam):
reader = PdfReader(fname)
form = reader.Root.AcroForm
fields = form[PdfFields]
for field in fields:
name = field[PdfT][1:-1]
field[PdfT] = f"{name}_merge{idx}"
if merged_acroform is None:
merged_acroform = form
else:
merged_acroform[PdfFields] += fields
writer.addpages(reader.pages)
writer.trailer.Root.AcroForm = merged_acroform
writer.write(outfile)
Můžeš si napsat pomocnou funkci nebo makro, ale jinak ne, C nemá výchozí hodnoty nebo konstruktory struktur.
#define FRAM(name) Fram name = { .staticS = 0b111 };
...
FRAM(fram);
fram.w1 = ...;
Nevím, vypisuješ obsah toho seznamu, tak bys měl vidět, co tam je a není, ale tipl bych, že třeba zadáváš ta jména jako "petr, pavel" a pak tam máš tu mezeru navíc ("petr" a " pavel").
A ty funkce parseTimespan a formatTimespan neexistují. Jde jen o princip.
Funkcí setInterval můžeš naplánovat periodické spouštění funkce, ve které ty časy upravíš.
function startTimer() {
setInterval(updateTimes, 1000);
}
function updateTimes() {
for (const el of document.querySelectorAll('.timer')) {
el.innerText = formatTimespan(parseTimespan(el.innerText) - 1);;
}
}
To časování není úplně přesné, takže takový pokus každou sekundu odečíst 1 sekundu se ti při delším běhu trochu rozjede. Ideální by bylo, kdybys tam měl finální čas expirace a vždycky z aktuálního času počítal zbývající dobu.
Tohle je těžké. Jedna věc je se na něčem zaseknout a hodně jiná věc je mít (zkopírovat) 5 funkcí a nechápat ani řádek.
Tak na ten kód chvíli zírej a uvidiš, že se funkcím předávají nějaké hodnoty jako parametry a vracejí jiné hodnoty jako výsledky. A pak stačí stejným způsobem tu konverzní funkci aplikovat na načtený text.
Třeba máš ty uzly očíslované, tak začátek a konec zadáš jako číslo.
Při návštěvě každého uzlu si můžeš uložit, odkud jsi na něj přišel a z toho pak zrekonstruovat cestu.
Protože příznak konce souboru (nebo chyby) se nastaví až když se pokusíš číst za koncem a protože getline tu výstupní proměnnou nijak nemění když nic nenačte.
- Čili načteš poslední řádek a vypíšeš ho.
- Soubor je vpořádku, tak čteš dál. Fakticky jsi na jeho konci, tak teď to selže a do myline se nic nevloží a je tam předchozí hodnota, kterou znova vypíšeš.
- Až teď detekuješ konec souboru a cyklus končí.
Můžeš dát přímo getline jako podmínku toho cyklu.
while (getline(myfile, myline))
{
cout << myline << '\n';
}
Nepoužil jsi nic z toho, co jsem ti poradil a máš to ještě blběji než předtím.