Follow along with the video below to see how to install our site as a web app on your home screen.
Huomio: This feature may not be available in some browsers.
Olisikohan tästä kyse:Nyt erikoinen visa mysql-tietäjälle.
Olen käyttänyt devissä php 7.2 + mysql:ää ja eräs ohjema alkoi nyt sanomaan että " Field 'money' doesn't have a default value"
Katsoin koodia ja siinä ei ole koskaan ollut arvoa insert-lauseessa koska arvo lisätään vasta insertin jälkeen erillisellä update:lla.
Päivitin devin muutama päivä sitten php 7.4:een, mutta mysql:n versio ei muuttunut.
Production-palvelimella tuo toimii, vaikka eihän tuon pitäisi toimia ollenkaan, vai onko siihen jokin FLAG ? olisi kiva tietää että wtf
Olisikohan tästä kyse:
mysql error 1364 Field doesn't have a default values
My table looks like create table try ( name varchar(8), CREATED_BY varchar(40) not null); and then I have a trigger to auto populate the CREATED_BY field create trigger autoPopulateAtInsert BEF...stackoverflow.com
for (( X=1; X<51; ++X ))
do
mkdir aa$X
let Y=0
for F in *.jpg
do
mv $F aa${X}/
let Y=Y+1
if [[ $Y == 100 ]]
then let Y=0 ; break ; fi
done
done
Eikös tuo pitäisi mennä ihan niin että kun määrittelee koko dokumentin kielen <html lang="fi"> ja sitten esimerkiksi kappaleelle <p lang=en"> tms.Accessibilitystä. Jos html tagiin on hyvä eli pitää laittaa lukijoita varten esim lang="fi" jos sivulla on suomenkielistä tekstiä, niin onko jotain tagia jos on joku englanninkielinen blokki sen saman suomalaiseksi määritellyn alla?
Accessibilitystä. Jos html tagiin on hyvä eli pitää laittaa lukijoita varten esim lang="fi" jos sivulla on suomenkielistä tekstiä, niin onko jotain tagia jos on joku englanninkielinen blokki sen saman suomalaiseksi määritellyn alla?
Olen itse käyttänyt vain tuota create-react-app skriptiä joka käyttää kai webpackkia.Tässä kun on harjoitellut tuota Reactia, niin on tullut kauhisteltua tuota pakettien määrää ja samalla myös noiden aukkojen.
Mikä lienee paras tapa Reactin käytöön. Kasata itse, käyttää esim Viteä? Onko jotain versiota mitä kannattaisi käyttää tuotannossa?
Toiset ohjeet sanoo että pitäisi joka päivä päivittää uusimpaan paketit, mikä tietenkin onnistuu kun yksin teen. Olisiko siis jossain tiimissä sovittu joku package-lock.json mitä käytetään. Tietenkin olen kuullut kauhutarinoita nyypiöistä niin kuin minä (ja kokeillutkin), jotka tulee projektiin ja pistää päivittäen koko projektin... itsellä ei ole tiimityöstä vielä mitään kokemusta, niin mitä olisi parhaimmat tavat?
Tästä on varmaan keskusteltu webbidevaus-podcastissa, mutta oon vasta jaksossa alle 30
Abauttiarallaa noin. package-lock kulkee repossa mukana. Repossa voi olla myös editori-asetuksiakin, notta kaikilla on formaatit&säännöt samallalailla automaagisesti (yleensä olettaen, että käytetään esim. vscodea). Tiimeissä/projekteissa on kyllä ohjeistukset/dokumentaatiot tehty alkuvaiheessa ja niitä ylläpidetään koko projektin eliniän ajan, että juurikin uudetkin jäsenet pääsee mukaan ilman, että tarvii joka asiaa käydä läpi yhdessä. Yleensä kyllä ainakin omalla kohdalla ollut tapana, että joku ottaa hoitaakseen uuden jäsenen briiffauksen, jossa käydään koodia ja käytäntöjä läpi ja katsotaan kaikki tärkeimmät linkit mm. dokumentaatioon ym yhdessä.Olisiko siis jossain tiimissä sovittu joku package-lock.json mitä käytetään.
Tässä kun on harjoitellut tuota Reactia, niin on tullut kauhisteltua tuota pakettien määrää ja samalla myös noiden aukkojen.
Mikä lienee paras tapa Reactin käytöön. Kasata itse, käyttää esim Viteä? Onko jotain versiota mitä kannattaisi käyttää tuotannossa?
Toiset ohjeet sanoo että pitäisi joka päivä päivittää uusimpaan paketit, mikä tietenkin onnistuu kun yksin teen. Olisiko siis jossain tiimissä sovittu joku package-lock.json mitä käytetään. Tietenkin olen kuullut kauhutarinoita nyypiöistä niin kuin minä (ja kokeillutkin), jotka tulee projektiin ja pistää päivittäen koko projektin... itsellä ei ole tiimityöstä vielä mitään kokemusta, niin mitä olisi parhaimmat tavat?
Mielestäni tärkeämpi (eikä "vain") pointti on se, että kun toinen repon ladattuaan pistääLock-tiedoston pointti on vain se, että saadaan tarkat versiot koko depsupuun paketeista
npm install
, nii se lataa samat paketit, eikä mahd. tuoreempia. Toki tän voi toteuttaa niinkin, että määrittelee package.jsonissa tarkemmin, mitä tahdotaan. Etuna se, että on kontrollia siihen mitä päivitetään ja kuinka pitkälle (tarpeellista, jos tietää mitä tekee ja miksi, muuten tarpeetonta).Mielestäni tärkeämpi (eikä "vain") pointti
Toki tän voi toteuttaa niinkin, että määrittelee package.jsonissa tarkemmin
No tuossa meinasin, että jos on tiedossa, että jotain ei voi/saa päivittää esim. minoreita enempää. En tietty tarkoittanut, että sillä tarkalleen ottaen lockia korvais, mut käytännön tasolla. Tällöin kukaan ei edes vahingossa päivitä. Siksi sulkeissa maininta asiasta.Aika vaikea/työlästä olisi replikoidan lock-tiedoston toimintaa noin kun siellä lockissa on koko puu mukana eikä vain suorat depsut. Eli depsujen depsujen depsut ad infinitum. Mutta ne tärkeimmät voi lukita tietty package.jsonissa ja se voi joskus olla tarpeellista.
enum IpAddrVersion {
V4(u8, u8, u8, u8),
V6(u16, u16, u16, u16, u16, u16, u16, u16),
}
type IP = IpAddrVersion;
impl IpAddrVersion {
fn is_valid_v6(&self) -> bool {
match self {
Self::V4(_,_,_,_) => false,
Self::V6(..) => true,
}
}
// TODO
fn regex_match_v6() -> bool {false}
fn to_string() {}
fn to_string_compressed() {}
fn from_string(input: &String) -> IpAddrVersion {
let v6_tuple: (u16, u16, u16, u16, u16, u16, u16, u16) = (0,0,0,0,0,0,0,1);
IpAddrVersion::V6(v6_tuple)
}
}
Koodi:enum IpAddrVersion { V4(u8, u8, u8, u8), V6(u16, u16, u16, u16, u16, u16, u16, u16), } type IP = IpAddrVersion; impl IpAddrVersion { fn is_valid_v6(&self) -> bool { match self { Self::V4(_,_,_,_) => false, Self::V6(..) => true, } } // TODO fn regex_match_v6() -> bool {false} fn to_string() {} fn to_string_compressed() {} fn from_string(input: &String) -> IpAddrVersion { let v6_tuple: (u16, u16, u16, u16, u16, u16, u16, u16) = (0,0,0,0,0,0,0,1); IpAddrVersion::V6(v6_tuple) } }
Olen opettelemassa Rustin alkeita ja nyt tuli tälläinen ongelma vastaan, että pitäisi tuple:sta saada purettua argumentit enum konstruktorille. Onko olemassa eleganttia tapaa purkaa v6_tuple argumenteiksi, joita V6 odottaa?
enum IpAddrVersion {
V4([u8; 4]),
V6([u16; 8]),
}
impl IpAddrVersion {
fn is_valid_v6(&self) -> bool {
match self {
Self::V4(..) => false,
Self::V6(..) => true,
}
}
// TODO
fn regex_match_v6() -> bool {false}
fn to_string() {}
fn to_string_compressed() {}
fn from_string(input: &str) -> IpAddrVersion {
let v6_array = [0,0,0,0,0,0,0,1];
IpAddrVersion::V6(v6_array)
}
}
Rust ei ole vielä tuttu, mutta eikö tuota voi tehdä destrukturoinnoilla?
fn from_string(input: &String) -> IpAddrVersion {
let v6_tuple: (u16, u16, u16, u16, u16, u16, u16, u16) = (0,0,0,0,0,0,0,1);
IpAddrVersion::V6(v6_tuple.0, v6_tuple.1, v6_tuple.2, v6_tuple.3, v6_tuple.4, v6_tuple.5, v6_tuple.6, v6_tuple.7)
}
Kiitos molemmille vastauksista!Voi toki, ja normaalisti varmasti ensimmäinen mitä tuossa tehtäisiin. Oletin, ehkäpä virheellisesti, että tämä oli jo tiedossa ja todettiin ei-elegantiksi koska sellaista oltiin vailla.
Koodi:fn from_string(input: &String) -> IpAddrVersion { let v6_tuple: (u16, u16, u16, u16, u16, u16, u16, u16) = (0,0,0,0,0,0,0,1); IpAddrVersion::V6(v6_tuple.0, v6_tuple.1, v6_tuple.2, v6_tuple.3, v6_tuple.4, v6_tuple.5, v6_tuple.6, v6_tuple.7) }
use regex::Regex;
use std::{u8, u16};
enum IpAddrVersion {
V4 {mask: u8, addr:[u8; 4]},
V6 {mask: u8, addr:[u16; 8]},
}
type IP = IpAddrVersion;
impl IpAddrVersion {
fn is_valid_v6(&self) -> bool {
match self {
Self::V4{..} => false,
Self::V6{..} => true,
}
}
// TODO
fn regex_match_v6() -> bool {false}
fn to_string(&self) -> String {
match self {
Self::V4{mask, addr} => {
format!("{}.{}.{}.{}/{}", addr[0], addr[1], addr[2], addr[3], mask)
},
Self::V6{mask, addr} => {
let mut ipv6 = String::new();
for block in addr {
ipv6.push_str(&format!("{:x}", block));
ipv6.push_str(":");
}
ipv6.pop();
ipv6.push_str("/");
ipv6.push_str(&mask.to_string());
return ipv6
},
}
}
fn to_string_compressed(&self) -> String {
match self {
Self::V4{mask, addr} => Self::to_string(&Self),
Self::V6{mask, addr} => {
let mut ipv6 = String::new();
let mut null_block_pattern: (usize, usize) = (0,0); // (start, length)
let mut null_block_pattern_record = null_block_pattern;
// find the longest consecutive null pattern
for (i, block) in addr.iter().enumerate() {
if block==0 {
if null_block_pattern.0 + null_block_pattern.1 == i{
null_block_pattern.1 +=1;
} else {
if null_block_pattern.1 > null_block_pattern_record.1 {
null_block_pattern_record = null_block_pattern;
}
null_block_pattern.0 = i;
null_block_pattern.1 = 1;
}
}
}
if null_block_pattern.1 > null_block_pattern_record.1 {
null_block_pattern = null_block_pattern_record;
}
for (i, block) in addr.iter().enumerate() {
if i >= null_block_pattern_record.1
&& i <= null_block_pattern_record.0 + null_block_pattern_record.1 {
continue;
} else if i == null_block_pattern_record.0 + null_block_pattern_record.1 {
ipv6.push_str(":");
} else {
ipv6.push_str(&format!("{:x}", block));
ipv6.push_str(":");
}
}
ipv6.pop();
ipv6.push_str("/");
ipv6.push_str(&mask.to_string());
return ipv6
},
}
}
fn from_string(input: &String) -> IpAddrVersion {
let reg_v4 = Regex::new(r"\.").unwrap();
if reg_v4.is_match(input) {
//println!("Found IPV4 input string!"); // DEBUG
let blocks = input.split('.');
let blocks: Vec<&str> = blocks.collect();
let mut v4_arr: [u8; 4] = [0;4];
if blocks.len()==4 {
for (i, val) in blocks.iter().enumerate() {
let block_u8 = u8::from_str_radix(val, 10);
match block_u8 {
Ok(v) => v4_arr = v,
Err(_) => panic!("Could not interpret {val} as an decimal number!"),
}
}
}
return IpAddrVersion::V4{mask: 0, addr: v4_arr}
}
let blocks = input.split(':');
let blocks: Vec<&str> = blocks.collect();
let mut v6_arr: [u16; 8] = [0;8];
if blocks.len()==8 {
for (i,val) in blocks.iter().enumerate() {
let block_u16 = u16::from_str_radix(val, 16);
match block_u16 {
Ok(v) => v6_arr = v,
Err(_) => panic!("Could not interpret {val} as an hexadecimal number!"),
}
}
}
return IpAddrVersion::V6{mask: 0, addr: v6_arr}
}
}
fn main() {
//let localhost = IpAddrVersion::V4(127, 0, 0, 1);
let localhost_v6 = IP::from_string(&String::from("2001:0:0:0:0:dc00:0:6"));
let localhost_v4 = IP::from_string(&String::from("127.0.0.1"));
println!("{}", localhost_v4.to_string());
println!("{}", localhost_v6.to_string());
//print_ip_addr(&String::from("localhost"), &localhost_v6);
//print_ip_addr(&String::from("localhost"), &localhost_v4); // verify localhost is still in scope!
}
fn print_ip_addr(host_name: &String, ip_addr: &IpAddrVersion) {
println!("Host: {} IP: {}", host_name, match ip_addr {
IP::V6{mask: m, addr: arr} => format!("{:?}/{}", arr, m),
IP::V4{mask: m, addr: [a,b,c,d]} => format!("{}.{}.{}.{}/{}",
a.to_string(), b.to_string(), c.to_string(), d.to_string(), m )
}
);
}
to_string-ongelma ratkeaa varmaan sanomalla yksinkertaisesti self.to_string(). Jälkimmäisestä en osaa sanoa valmista ratkaisua työntämättä koko höskää kääntäjälle ja yrittämällä siitä, mutta block on nyt nähtävästi &u16, kun taas 0 on jokin epämääräinen luku. Saattaisi lähteä toimimaan joko sanomalla *block == 0 tai kenties block == (0 as u16).Rich (BB code):use regex::Regex; use std::{u8, u16}; enum IpAddrVersion { V4 {mask: u8, addr:[u8; 4]}, V6 {mask: u8, addr:[u16; 8]}, } type IP = IpAddrVersion; impl IpAddrVersion { fn is_valid_v6(&self) -> bool { match self { Self::V4{..} => false, Self::V6{..} => true, } } // TODO fn regex_match_v6() -> bool {false} fn to_string(&self) -> String { match self { Self::V4{mask, addr} => { format!("{}.{}.{}.{}/{}", addr[0], addr[1], addr[2], addr[3], mask) }, Self::V6{mask, addr} => { let mut ipv6 = String::new(); for block in addr { ipv6.push_str(&format!("{:x}", block)); ipv6.push_str(":"); } ipv6.pop(); ipv6.push_str("/"); ipv6.push_str(&mask.to_string()); return ipv6 }, } } fn to_string_compressed(&self) -> String { match self { Self::V4{mask, addr} => Self::to_string(&Self), Self::V6{mask, addr} => { let mut ipv6 = String::new(); let mut null_block_pattern: (usize, usize) = (0,0); // (start, length) let mut null_block_pattern_record = null_block_pattern; // find the longest consecutive null pattern for (i, block) in addr.iter().enumerate() { if block==0 { if null_block_pattern.0 + null_block_pattern.1 == i{ null_block_pattern.1 +=1; } else { if null_block_pattern.1 > null_block_pattern_record.1 { null_block_pattern_record = null_block_pattern; } null_block_pattern.0 = i; null_block_pattern.1 = 1; } } } if null_block_pattern.1 > null_block_pattern_record.1 { null_block_pattern = null_block_pattern_record; } for (i, block) in addr.iter().enumerate() { if i >= null_block_pattern_record.1 && i <= null_block_pattern_record.0 + null_block_pattern_record.1 { continue; } else if i == null_block_pattern_record.0 + null_block_pattern_record.1 { ipv6.push_str(":"); } else { ipv6.push_str(&format!("{:x}", block)); ipv6.push_str(":"); } } ipv6.pop(); ipv6.push_str("/"); ipv6.push_str(&mask.to_string()); return ipv6 }, } } fn from_string(input: &String) -> IpAddrVersion { let reg_v4 = Regex::new(r"\.").unwrap(); if reg_v4.is_match(input) { //println!("Found IPV4 input string!"); // DEBUG let blocks = input.split('.'); let blocks: Vec<&str> = blocks.collect(); let mut v4_arr: [u8; 4] = [0;4]; if blocks.len()==4 { for (i, val) in blocks.iter().enumerate() { let block_u8 = u8::from_str_radix(val, 10); match block_u8 { Ok(v) => v4_arr = v, Err(_) => panic!("Could not interpret {val} as an decimal number!"), } } } return IpAddrVersion::V4{mask: 0, addr: v4_arr} } let blocks = input.split(':'); let blocks: Vec<&str> = blocks.collect(); let mut v6_arr: [u16; 8] = [0;8]; if blocks.len()==8 { for (i,val) in blocks.iter().enumerate() { let block_u16 = u16::from_str_radix(val, 16); match block_u16 { Ok(v) => v6_arr = v, Err(_) => panic!("Could not interpret {val} as an hexadecimal number!"), } } } return IpAddrVersion::V6{mask: 0, addr: v6_arr} } } fn main() { //let localhost = IpAddrVersion::V4(127, 0, 0, 1); let localhost_v6 = IP::from_string(&String::from("2001:0:0:0:0:dc00:0:6")); let localhost_v4 = IP::from_string(&String::from("127.0.0.1")); println!("{}", localhost_v4.to_string()); println!("{}", localhost_v6.to_string()); //print_ip_addr(&String::from("localhost"), &localhost_v6); //print_ip_addr(&String::from("localhost"), &localhost_v4); // verify localhost is still in scope! } fn print_ip_addr(host_name: &String, ip_addr: &IpAddrVersion) { println!("Host: {} IP: {}", host_name, match ip_addr { IP::V6{mask: m, addr: arr} => format!("{:?}/{}", arr, m), IP::V4{mask: m, addr: [a,b,c,d]} => format!("{}.{}.{}.{}/{}", a.to_string(), b.to_string(), c.to_string(), d.to_string(), m ) } ); }
Olen jatkanut koodiharjoitustani Rustilla ja taas muutama aika lähtötason ongelma, jotka korostettu oranssilla. Miten tuo self passataan enumin metodilta toiselle? Ja if vertailu tuottaa seuraavan virheen: can't compare `&u16` with `{integer}` - mikä on oikea tapa korjata tämä?
Alkaa olemaan taas pää niin jumissa, ettei aukene itsestään
Tällähän se lähti toimiin, kiitosto_string-ongelma ratkeaa varmaan sanomalla yksinkertaisesti self.to_string(). Jälkimmäisestä en osaa sanoa valmista ratkaisua työntämättä koko höskää kääntäjälle ja yrittämällä siitä, mutta block on nyt nähtävästi &u16, kun taas 0 on jokin epämääräinen luku. Saattaisi lähteä toimimaan joko sanomalla *block == 0 tai kenties block == (0 as u16).
interface QueryResultProps {
result: UseQueryResult;
children: React.ReactNode;
}
const QueryResult: React.FC<QueryResultProps> = ({ result, children }) => {
if (result.isLoading)
return <p>Loading...</p>;
if (result.isError)
return <p>{`Error: ${result.error}`}</p>;
if (result.isSuccess)
return <Fragment>{children}</Fragment>;
return null;
};
const items = useQuery('items', getItems);
<QueryResult result={items}>
<ul>
{items.data.map((item: Item) => <li>{item.title}</li>)}
</ul>
</QueryResult>
import TextBox from './TextBox';
const tmi = require('tmi.js');
const client = new tmi.Client({
channels: [ 'MrSyS0p' ] //Tähän mikä tahansa "aktiivinen" kanava
});
client.connect();
console.clear();
client.on('message', (channel, tags, message, self) => {
// "Alca: Hello, World!"
console.log(`${tags['display-name']}: ${message}`);
});
function Container() {
const text = [
"Viesti1",
"Viesti2",
"Viesti3",
"Viesti4",
"Viesti5"
]
return (
<div className='container'>
{
text.map((item, index) => {
return <TextBox key={index} Msg={item}/>
})
}
</div>
);
}
export default Container;
React-osaamisessani on näköjään suuria aukkoja. Käytän react-queryä ja sain ajatuksen yleisestä wrapperistä joka hoitaisi loading/error yms. tilojen esittämisen:
Koodi:interface QueryResultProps { result: UseQueryResult; children: React.ReactNode; } const QueryResult: React.FC<QueryResultProps> = ({ result, children }) => { if (result.isLoading) return <p>Loading...</p>; if (result.isError) return <p>{`Error: ${result.error}`}</p>; if (result.isSuccess) return <Fragment>{children}</Fragment>; return null; };
Ja voisin käyttää sitä tähän tapaan:
Koodi:const items = useQuery('items', getItems); <QueryResult result={items}> <ul> {items.data.map((item: Item) => <li>{item.title}</li>)} </ul> </QueryResult>
Mutta tuosta seuraa virhe "Uncaught TypeError: Cannot read properties of undefined (reading 'items')" joka indikoisi sitä että childrenit rendataan/mountataan riippumatta parentin tilasta? Eli nyt joudun lisäämään tuonne childreniin ehdollisen renderöinnin items.isSuccessin kanssa ja juuri siitä haluaisin eroon. Olenko ymmärtänyt jotain pahasti väärin ja miten tuollaisen kuvatunlaisen mekanismin toteutus onnistuisi Reactissa?
if (isLoading) return <Loading />
if (error) return <Error error={error} />
if (data.length === 0) <NoResults />
const QueryResult: React.FC<QueryResultProps> = ({ result }) => {
if (result.isLoading) return <p>Loading...</p>;
if (result.isError) return <p>{`Error: ${result.error}`}</p>;
return null;
};
// käyttö:
const items = useQuery('items', getItems);
if (!items.isSuccess) return <QueryResult result={items} />
return (
<ul>
{items.data.map((item: Item) => <li>{item.title}</li>)}
</ul>
)
Joo, noin react-queryä olen normaalisti käyttänyt, mutta kun lähes samaa toistaa joka näkymässä useampaan kertaan niin tuli mieleen olisiko abstraktimpaa tapaa toteuttaa sama.Mitä yleensä nähnyt queryä käytettävän niin on ollut lataamiselle ja errorille omat komponentit ja vaan laitettu ne jokasen paikkaan erikseen, tyyliin:
Koodi:if (isLoading) return <Loading /> if (error) return <Error error={error} /> if (data.length === 0) <NoResults />
const items = useQuery('items', getItems);
<QueryResult query={items} result={(data: Item[]) =>
<ul>
{data.map((item: Item) => <li>{item.title}</li>)}
</ul>
}/>
Ideoin tässä S3 / google bucketin käyttöä, mutta niissähän tiedostot on jaettavissa suoralla linkillä kenelle vaan.
Ja jos taas lukee palvelinpuolen ohjelmalla tiedoston bucketista käyttäjälle niin tämähän kuluttaa sitten taas kallista app-serverin kaistaa.
Miten tämä on yleensä ratkaistu ? Voiko bucketista pyytää kertakäyttölinkin tms. linkin mikä toimisi vaikka 24h ?
Ja toinen kysymys, ei ole hirveästi ainakaan hyvää kokemusta dockerista tms, mutta voisiko sitä tai kubernetsiä käyttää siihen että teen lataan jostain valmiin python3 imagen, laitan siihen cronilla oman ohjelman pyörimään ajastetusti ja sitten ostan jostain palvelimen johon voi ladata tuon imagen suoraan ? ja tarvittaessa siis saisi näin saman ohjelman pyörimään yhtä aikaa monella eri koneella helposti? Ohjelma ei sisällä inbound-liikennettä joten http-palvelinta ei tarvitse olla. Taka-ajatukseni on ettei siis tarvitisi manuaalisesti ylläpitää ja päivitellä mitään virtuaalilinuxeja missään hefnerillä... ja mahdollisesti saisi vielä kaikki ympäristöt päivittymään kunhan pushaa uuden koodin bitbuckettiin...
Kuulostaa koulutehtävältä. Itse lähtisin kahdella sisäkkäisellä loopilla missä missä ulompi kasvattaa ympyrän sädettä ja sisempi käy kulman suuruuksia välilä 0-2π. Sitten tarkistaa osuuko piste kolmion sisälle. Tuosta sitten vaan säätää riittävä tarkkuus, useamman samalla etäisyydellä olevan kolmion hallinta ja mukava ohjelmointikieli.Miten lasketaan pisteen ja kolmion välinen etäisyys? Pitäsi löytää pisteelle lähin kolmio, kolmoita voi olla tuhansia. Piste ei ole minkään kolmion päällä.
Ei ole koulutehtävä, eikä itseasiassia ongelmana loopit yms. vaan puhdas matematiikka, että miten valitaan pisteelle lähin kolmio.Kuulostaa koulutehtävältä. Itse lähtisin kahdella sisäkkäisellä loopilla missä missä ulompi kasvattaa ympyrän sädettä ja sisempi käy kulman suuruuksia välilä 0-2π. Sitten tarkistaa osuuko piste kolmion sisälle. Tuosta sitten vaan säätää riittävä tarkkuus, useamman samalla etäisyydellä olevan kolmion hallinta ja mukava ohjelmointikieli.