Tản màn về việc tạo dựng doanh nghiệp, những dòng tôi viết dưới đây là những suy nghĩ rời rạc từ chính những thứ tôi
nhìn thấy.
Về mặt lý tưởng, chủ doanh nghiệp / công tyọ là những người nhìn thấy vấn đề của những người xung quanh, hay to
tát hơn là cả xả hội. Họ tìm cách giải quyết vấn đề đó. Cuối cùng là họ được trả thưởng cho giải pháp mà họ đưa ra.
Lợi nhuận và tiền bạc là những thứ có được ở điểm cuối, hoặc ít nhất là gần cuối của quá trình trình:
Nhìn ra vấn đề
Tìm ra giải pháp khi này giải pháp vẫn trên giấy
Tạo ra giải pháp khi này giải pháp không còn trên giấy, nó đã có tính thực tiễn
Nhận phần thưởng
Tuy nhiên, ta cần phải làm rõ 5 điểm sau:
[1] Nhìn ra vấn đề, chưa chắc đã tìm ra giải pháp.
[2] Tìm ra giải pháp trên giấy rồi đó, nhưng chưa chắc đã tạo ra được giải pháp, hay làm nó trở nên thực
tiễn hơn
[3] Tạo ra giải pháp rồi, đúng là nó đã có tính thực tiễn rồi, nhưng chưa chắc đã nhận được phần thưởng.
[4] Giá trị phần thưởng không tỷ lệ thuận, lũy tiến theo độ khó của vấn đề, hay nỗ lực để giải quyết vấn đề đó.
[5] Sau cùng, đây là ý quan trọng nhất. Việc tạo ra doanh nghiệp / công tyKHÔNG CÓ NGHĨA là đi giải quyết vấn
đề của xã hội. Có thể, nó rất đơn giản là đi kiếm tiền. Hoàn toàn chả có gì nhân bản, nhân loại hay cao siêu ở đây cả.
Họ kiếm tiền, mục đích tối thượng ở đây là kiếm tiền, tạo lợi nhuận, tối đa hóa lợi nhuận bằng mọi cách! Chấm hết!
Đây là mô hình mà cá nhân tôi chán ghét nhất.
Khi tôi tạo doanh nghiệp, chắc chắn là tôi không chọn con đường này!
Nối tiếp bài viết Cách build Monero, bài viết này tập trung nói về cách build Monero-GUI, release v0.18.5.4.
Sau khi build xong, bạn sẽ sử dụng Monero GUI dễ dàng hơn. Ở phiên bản này, vẫn đang sử dụng là QT5 cho giao diện GUI. Ở phiên bản kế tiếp sẽ là QT6
Ở lần build tới, để update các repository phụ, chạy command sau:
$ git submodule update --init --recursive
Bước 3: Build
$ make release
Và đây là kết quả thu được.
$ tree build/release/bin
build/release/bin
├── monerod
└── monero-wallet-gui
Khi bạn chạy monero-wallet-gui, mọi config của bạn bao gồm nơi chứa wallet và node nằm ở
~/.config/monero-project/monero-core.conf. Mỗi khi chạy lại, monero-wallet-gui sẽ đọc file
này.
Bài viết đến đây là kết thúc! Nhân tiện thì giả sử bạn đang cần giao dịch ngay mà không muốn mất
thời gian đồng bộ hóa giữ liệu. Bạn có thể sử dụng node của tôi: monero.hexalink.xyz:18081.
Node: monero.hexalink.xyz || Port: 18081
Nếu bạn sử dụng node monero.hexalink.xyz:18081 này, tôi khẳng định là tôi mới giúp bạn tiết
kiệm được ít nhất là 3-5 ngày đồng bộ hóa dữ liệu rồi đó!
III. Lời cảm ơn
Tôi đã gặp khó khăn trong lúc build monero-gui, trong release v0.18.5.4, source code sử dụng
QT5, tuy nhiên hướng dẫn mà tôi đọc lại thuộc branch master, lại là dành cho QT6. Do đó mà
thiếu qt5-qtdeclarative-devel qt5-qtsvg-devel.
Mọi thứ đã có thể lâu hơn rất nhiều nếu không có sự hỗ trợ của ChatGPT. Cảm ơn rất nhiều!
Để test tốc độ mạng giữa các máy tính nội bộ, chúng ta hoàn toàn có thể cân nhắc sử dụng iperf3.
Tôi biết đến công cụ này khi đang tìm cách backup blockchain bitcoin. Thực sự mà nói, tốc độ copy data
từ máy tính cá nhân (client) đến máy NAS (server) khá là chậm.
Điều này khiển tôi phải thực sự kiểm tra network nội bộ của mình. Công cụ mà tôi sử dụng là iperf3.
Nó có sẵn trên máy NAS server (Unraid OS) và cả trên (Fedora).
Thực sự là tôi chả cần phải cài gì thêm cả. Khá là tiện. 😙
II. Nội dung
[1] Mô hình truyền dữ liệu
Bước 1: Trên máy NAS Server, chạy iperf3 ở chế độ server
Dựa theo hình vẽ trên, máy server có ip là 192.168.1.3, chạy command sau:
$ iperf3 -s# Command outputs-----------------------------------------------------------
Server listening on 5201 (test#1)-----------------------------------------------------------
Bước 2: Trên máy client, chạy iperf3 ở chế độ client và kết nối đến server
Ở trên máy client, có ip là 192.168.1.2, chạy command sau:
Tôi cần phải nói là tôi không bao giờ nghĩ đến việc mình sẽ viết blog về chủ đề này.
Rsync - Nó quá đơn giản, nó quá dễ dàng.
Nhưng mà mỗi lần đụng đến rsync, tôi đều phải rsync --help hoặc tệ hơn là dùng chatgpt. Tôi
luôn đặt ra những ranh giới cho chính mình khi nào cần và khi nào không cần dùng đến chatgpt.
Và tôi cảm giác thật là con người khi làm như vậy.
Nói sơ qua một chút thì rsync là một command dùng để sao lưu dữ liệu. Tôi đang có nhu cầu sao lưu
dữ liệu của bitcoin knots (Bitcoin Blake2B). Việc này sẽ giúp tôi giảm thời gian khi triển khai node mới.
--archive: chế độ lưu trữ, nó là tổng hợp của rất nhiều flag. (xem kỹ ở đây)
--human-readable: khi show log, dữ liệu dễ đọc hơn
--info=progress2: hiển thị progress với phần trăm
Lưu ý:
Path của thư mục gốc SRC/mnt/disk_2/CryptoCurrency/Bitcoin_knots/ sẽ cần / ở cuối nếu mục đích là copy toàn bộ nội dung của nó đến thư mục đích đến DEST.
Nếu mà không có / ở cuối của SRC, rsync sẽ tạo thư mục con có tên là Bitcoin_knots nằm bên trong DEST.
CMR (Conventional Magnetic Recording): Ghi từ tính thông thường
SMR (Shingled Magnetic Recording): Ghi từ tính kiểu lợp ngói
Tiêu chí
CMR
SMR
Tên đầy đủ
Conventional Magnetic Recording
Shingled Magnetic Recording
Cách bố trí track
Không chồng lấn
Chồng lấn một phần
Mật độ lưu trữ
Thấp hơn
Cao hơn
Ghi tuần tự
Tốt
Tốt
Ghi ngẫu nhiên
Tốt
Chậm hơn
Ghi đè dữ liệu
Tốt
Chậm hơn
Giá trên mỗi TB
Cao hơn
Rẻ hơn
Ứng dụng điển hình
NAS, máy chủ, workload hỗn hợp
Backup, lưu trữ lạnh, dữ liệu ít thay đổi
SMR do thiết kế theo kiểu lợp ngói, các rãnh từ bị chồng lấn(1), đầu ghi thì lớn(2). Hai nguyên nhân trên gây ảnh hưởng không tốt đến quá trình ghi dữ liệu.
Khi ghi dữ liệu trên một rãnh từ tính, việc này hoàn toàn có thể làm sai dữ liệu ở các rãnh từ tính lân cận.
Rãnh từ tính xếp lớp, đầu ghi thì lại to. Chỉ cần ghi dữ liệu trên một rãnh từ tính, HDD thực tế phải ghi dữ liệu trên hai rãnh lân cận, nhằm đảm bảo độ chính xác 🥲!
Tóm tắt lại thì nếu mà mua ổ đĩa làm NAS, 100% là nên chọn CMR - Conventional Magnetic Recording 👨🏻🔧.
Lưu ý, đây không phải là cách query nhanh nhất. Tôi thấy có sequence scan trong Explain Execution Plan. Hiện tại thì data của tôi vẫn chưa
đủ lớn để tối ưu hóa. Nó nên dành cho bài post khác chứ không phải là ngay bây giờ.
[2] Explain Execution Plan
Đây không phải là cách nhanh nhất. Tuy nhiên, đây chắc chắn là câu query dễ chịu nhất để viết và đọc.
Tôi sẽ mở đầu bài viết này từ vấn đề tôi đã gặp phải!
Trong dự án Dolphin Shopkit, mô hình dữ liệu bao gồm Collection (Bộ sưu tập) và
Product (Sản phẩm). Đây là mối quan hệ many-many, Một bộ sưu tập có nhiều sản phẩm, một sản phẩm
thuộc nhiều bộ sưu tập.
Nhu cầu của tôi là: thay đổi thứ tự hiển thị các sản phẩm này trong bộ sưu tập. Tâm sự một chút thì
đây là lần đầu tiên tôi làm tính năng kiểu như thế này! Và tôi tin là trong tương lai tôi sẽ còn gặp lại nó.
Bài post như là cách để tôi tra cứu trong tương lai khi cần thiết.
Để dễ hình dung, đây là database schema!
Product & Product Variant schema
Hãy chú ý cột product_display_order trong bảng collections_products.
Cách làm sẽ là như sau, tôi sẽ chỉ phương hướng, chút nữa sẽ là mã nguồn để tham khảo.
Phía UI sẽ có các thao tác drag-n-drop (kéo thả), client sẽ gửi lên server danh sách collection_product_id_list
với thứ tự mới.
Dưới database, sẽ chạy sql query cập nhật tất cả các collections_products entry record với giá trị cột product_display_order
mới.
collection_product_id
product_display_order(Cũ)
product_display_order(Mới)
1000
1
5
1001
2
4
1002
3
3
1003
4
2
1004
5
1
Keyword để tra cứu ở đây là ORDINALITY (Postgresql). Mục tiêu là từ danh sách collection_product_id với trật tự mới,
ta sẽ thêm cột dữ liệu tuần tự product_display_order.
Bạn thấy đó, kết quả là chỉ cần duy nhất một câu SQL là giải quyết được bài toán thay đổi thứ tự.
Hey, nhưng nếu bạn nghĩ rằng bài viết này vậy là xong thì chưa đâu nhé! Sẽ còn vài điều quan trọng nữa, ít nhất là cho
tôi - người dùng Phoenix Webframework, LiveView và SortableJS để thay đổi vị trí Product trong Collection
[1] Về phía frontend (HTML), đây là code sample, chú ý phx-hook
[4] Phía Ecto (Database Libary) khi chạy sql query
defreorder_collection_product_list(collection_product_id_list)domod_collection_product_id_list=collection_product_id_list|>Enum.map(&String.to_integer/1)query="""
UPDATE collections_products cp
SET product_display_order = x.product_display_order
FROM (SELECT * FROM unnest($1::bigint[])
WITH ORDINALITY AS t(collection_product_id, product_display_order)) as x
WHERE cp.id = x.collection_product_id;
"""Ecto.Adapters.SQL.query(Repo,query,[mod_collection_product_id_list])end
Credit: để giải quyết bài toán này, tôi đã dùng ChatGPT để hỗ trợ. Nếu không có ChatGPT, khả năng cao
là tôi sẽ mở database session, sau đó update từng dòng một, rồi commit session. Phương pháp sẽ
không thể nào gọn gàng như hiện tại nếu thiếu ORDINALITY.
Nhân tiện, từ khi tôi triển khai tính năng này đến thời điểm viết bài cũng cả tháng rồi, tuy nhiên, rất
khó nhớ. Tôi viết blog cũng vì lý do này, mỗi lần viết là lại thêm một lần nhớ, ORDINALITY này rất
thú vị, để quên thì thật đáng tiếc.
-crf 30: Constant Rate Factor. It refers to video quality. 0 means the best quality, 40+ means super compressed, worse quality. (tbh, I only test Constant Rate Factor 30)
-b:v 0: Do not configure fixed video bitrate.
-f segment -segment_time 3600: For each one hour, create a video file.
-reset_timestamps 1: when create video, start timestamps at 1 (by default, it starts from the end timestamps of previous video)
-strftime 1 "%Y-%m-%dT%H%M%S.webm": Output with filename format.
Credit
ChatGPT helps me so much with ffmpeg, without it, I can’t understand all the ffmpeg options quickyly.
Bài viết này miêu tả những kỹ thuật và lưu ý mà tôi đã học được để sử dụng cảm biển ZMPT101B.
Ngay khi mua cảm biến ZMPT101B, cần tinh chỉnh triết áp với Serial Plotter, xung không nên bị bè ở đầu, mất góc ở đỉnh.
Tiếp theo, tìm giá trị tham chiếu zero point ở 0 voltage AC.
Cuối cùng là tìm hệ số chuyển đổi Scale.
Mỗi cảm biến lại có những sai số khác nhau, hoàn toàn không thể sử dụng hệ số chuyển đổi (SCALE)của cảm biến này áp dụng cho cảm biển khác, mặc dù là cùng một model.
1. Vặn triết áp và theo dõi trên Serial Plotter
Trước khi điều chỉnh, bắt buộc phải cắm dây điện xoay chiều vào cảm biến ZMPT101B. Bên cạnh đó, phải có phần mềm Arduino-IDE, mở công cụ Serial Plotter. Arduino-CLI không có tính năng này.
Việc điều chỉnh triết áp dựa trên các tiêu chí sau:
Giá trị / biên độ là lớn nhất khi xem trên Serial
Đỉnh của sóng không được phép bè ra, mất góc nhọn.
14:11:15.109 -> Zero Point: 511
14:11:16.106 -> Zero Point: 511
...
14:11:22.113 -> Zero Point: 511
14:11:23.109 -> Zero Point: 511
Bên cảm biến của tôi, kết quả là 511.
3. Tìm hệ số chuyển đổi scale
Ở đoạn này bắt buộc phải có đồng hồ chính xác bên ngoài, đo trước hiệu điện thế điện xoay chiều AC. Sau đó, gài giá trị vào EXPECTED_VOLTAGE
ở đoạn code dưới đây và chạy. Khi chạy code, đảm bảo dây AC cần đo đã gắn vào cảm biến ZMPT101B chắc chắn.
Ở bên nhà tôi, hiệu điện thế đo được là 233V (Hoàn toàn không phải là 220V đâu nhé). Giá trị scale tôi thu được là 1.38
#include<math.h>constintZMPT101B_PIN=A0;constfloatEXPECTED_VOLTAGE=233.0;constunsignedintzeroPoint=511;constintWINDOW_TIME=1000;unsignedlongsumOfSquareOfSampleDataMinusZeroPoint=0;unsignedlongsampleCounter=0;unsignedlongstartTime;floatrootMeanSquare=0.0f;voidsetup(){Serial.begin(115200);startTime=millis();}voidloop(){intsampleData=analogRead(ZMPT101B_PIN);sumOfSquareOfSampleDataMinusZeroPoint+=(sampleData-zeroPoint)*(sampleData-zeroPoint);sampleCounter+=1;if(millis()-startTime>=WINDOW_TIME){rootMeanSquare=sqrt((float)sumOfSquareOfSampleDataMinusZeroPoint/sampleCounter);floatscale=EXPECTED_VOLTAGE/rootMeanSquare;Serial.print("Root Mean Square: ");Serial.print(rootMeanSquare);Serial.print(" (in ");Serial.print(sampleCounter);Serial.print(" samples). Scale: ");Serial.println(scale);sumOfSquareOfSampleDataMinusZeroPoint=0;sampleCounter=0;startTime=millis();}}
14:04:15.083 -> Voltage: 233.00 | Root Mean Square: 168.56 (in 17856 samples) | Scale: 1.38
14:04:17.108 -> Voltage: 233.00 | Root Mean Square: 168.53 (in 17855 samples) | Scale: 1.38
14:04:19.099 -> Voltage: 233.00 | Root Mean Square: 168.69 (in 17855 samples) | Scale: 1.38
14:04:21.088 -> Voltage: 233.00 | Root Mean Square: 168.73 (in 17855 samples) | Scale: 1.38
Phương pháp như sau:
Tính toán giá trị hiệu dụng (Root Mean Square - RMS) của giá trị sensor với giá trị tham chiếu (zero point) trong một khoảng thời gian (WINDOW_TIME)
Kết hợp với giá trị hiệu điện thế AC đo đạc từ một đồng hồ đo điện khác (EXPECTED_VOLTAGE)
Tồn tại sự tương quan giữa giá trị hiệu dụng của sensor và hiệu điện thế EXPECTED_VOLTAGE, tỷ lệ này ta gọi là SCALE(Hệ số chuyển đổi)
Tính toán tỷ lệ SCALE = EXPECTED_VOLTAGE / RMS
4. Tìm giá trị hiệu điện thế tức thời
Sau khi tìm được giá trị SCALE - hệ số chuyển đổi, ví dụ cảm biến cho ta giá trị là X, muốn tìm ra hiệu điện thế tức thời, ta làm như sau:
Vtức_thời = (X - ZeroPoint) * Scale
5. Lưu ý
Một khi đã tinh chỉnh xong, không được phép vặn triết áp. Nếu mà lỡ vặn, phải làm lại từ đầu.