/ Forside / Teknologi / Udvikling / Perl / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
Perl
#NavnPoint
bjarneA 141
poul_from 50
soccer 30
Nicknack 14
Tmpj 0
random colour...
Fra : Flemming Hansen


Dato : 15-08-03 12:40

Hejsa,

Jeg har lavet et funktion som vælger en unik farve til hver bruger... Jeg
har ihvertfald prøvet at lave det, men problemet er bare at funktionen
virker ikke som forventet. Min fremgangsmåde er vist ikke helt optimal og
jeg laver nok en eller anden fejl i while-løkken. Sådan ser mine 2
funktioner:

############################################################################
###################
# pick a random colour to the user.
sub color2 {
my(@color, $rnd_color, $random_color);

@color =
('990077','cc0066','6600cc','00cc66','66cc00','ff0033','3399cc','996600','12
3abc');

srand($$|time);

$rnd_color = "";
$random_color = int(rand($#color + 1));
$rnd_color = $color[$random_color];

return $rnd_color;
}

############################################################################
###################
# pick a random colour to the user and checks for unik color.
sub color{

my @user_data = '';
my $found = 0;
my $color;
opendir(FILE, "$chat_db/user") || die "Can't open user data files";
my @color = readdir(FILE);
closedir(FILE);

do{
$color = color2();
foreach (@color){
if($_ ne '.' && $_ ne '..'){
open(FILE, "$chat_db/user/$_") || die "can't open user data
file";
lock(FILE);
@user_data = <FILE>;
unlock(FILE);
close(FILE);
}
chomp(@user_data);
if(grep {/$color/} @user_data){
$found = 1;
}else{
$found = 0;
}
}
}while($found >= 1);
return $color;
}

Kan dette gøres på en bedre og kortere måde? Og jeg ved at der ikke er en
kontrol mekanisme på hvis der kommer en 10. bruger så bliver man nok
hængende på while-løkken... Men altså funktionen finder en farve til
brugeren, checker om andre brugere har den, men hvis en anden har den vælger
den alligevel ikke en anden...



 
 
Peter Makholm (15-08-2003)
Kommentar
Fra : Peter Makholm


Dato : 15-08-03 13:08

"Flemming Hansen" <dsl34257@vip.cybercity.dk> writes:

> Kan dette gøres på en bedre og kortere måde? Og jeg ved at der ikke er en
> kontrol mekanisme på hvis der kommer en 10. bruger så bliver man nok
> hængende på while-løkken...


Jeg ville nok gøre ret meget anderledes. Først ville jeg generalisere
din color2-funktion til at tage listen af mulige farver som argument:

sub rand_elem {
my @elements = @_;
return $elements[rand($#elements + 1)];
}

Så ville jeg nok gemme tilstanden i en GDBM-fil (eller en anden
ligende ting) som kan ties til en hash. Så ville jeg trække de farver
ud der ikke var allokeret og vælge en af dem:

sub get_color {
my $user = shift;

my %db;
tie %db, 'GDBM_File', $color_db, &GDBM_WRCREAT, 0640;

@colors = grep { $db{$_} eq "" } keys %db;
return undef unless @colors; # None available colors

$user_color = rand_elem @colors;
$db{$user_color} = $user;
untie %db;

return $user_color;
}

sub release_color {
my $color = shift;

my %db;
tie %db, 'GDBM_File', $color_db, &GDBM_WRCREAT, 0640;
$db{$color} = "";
untie %db;
}


Måske med en smule mere error-handling, men det er en øvelse for
læseren.


--
Peter Makholm | Sit back and watch the messages. This is actually
peter@makholm.net | more important than one might think as there is a
http://hacking.dk | bug in GNU Mach whereby hitting a key during the
| boot process causes the kernel to panic
| -- GNU Hurd Installation Guide

Flemming Hansen (15-08-2003)
Kommentar
Fra : Flemming Hansen


Dato : 15-08-03 13:16

>
> Jeg ville nok gøre ret meget anderledes. Først ville jeg generalisere
> din color2-funktion til at tage listen af mulige farver som argument:
>
> sub rand_elem {
> my @elements = @_;
> return $elements[rand($#elements + 1)];
> }

OK, det ser noget kortere og mere forståelig ud

>
> Så ville jeg nok gemme tilstanden i en GDBM-fil (eller en anden
> ligende ting) som kan ties til en hash. Så ville jeg trække de farver
> ud der ikke var allokeret og vælge en af dem:

det der forstår jeg slet ikke. Jeg kan opfættes som en nybegynder når jeg
kigger på din kode Jeg kunne kopiere det og sætte ind i mit script og
håbe på at det virkede, men jeg vil helst kunne fårsto hvad der foregik
Kan det gøres på en nemmere måde? Altså uden at bruge nogle andre moduler?
jeg mener med noget nybegynder kode?



Peter Makholm (15-08-2003)
Kommentar
Fra : Peter Makholm


Dato : 15-08-03 13:44

"Flemming Hansen" <dsl34257@vip.cybercity.dk> writes:

>> sub rand_elem {
>> my @elements = @_;
>> return $elements[rand($#elements + 1)];
>> }
>
> OK, det ser noget kortere og mere forståelig ud

Den eneste reele forskel er at jeg tager listen af elementer som
argument. Resten er bare et stilistisk spørgsmål.

>> Så ville jeg nok gemme tilstanden i en GDBM-fil (eller en anden
>> ligende ting) som kan ties til en hash. Så ville jeg trække de farver
>> ud der ikke var allokeret og vælge en af dem:
>
> det der forstår jeg slet ikke. Jeg kan opfættes som en nybegynder når jeg
> kigger på din kode

Ok, det kunne være at jeg skulle nøjes med at ridse ideen op og selv
lad dig skrive kode. Så får du lettere ved at vedligeholde koden.

1. Find ud af hvilke farver der er ledige.

2. Hvis der ikke er nogle ledige farver kan du returnerer undef eller
kalde die. Alt må være bedre end en uendelig løkke.

3. Kald rand_elem på listen med de ledige farver.

4. Sørg for at markere at farven ikke er ledig længere.

5. Returner farven.


Det svære er helt klart punkt 1. En teknisk mere enkel måde at gøre
det på kunne være at vedligehold en fil men en liste over ledige
farver, en farve på hver linje. Så kommer punkt et til at skulle løses
ale følgende:

A. Åben filen (for læsning og skrivning) og lås den.

B. Læs farverne ind

C. Foretag punkt 2 og 3

D. Alle farverne undtagen den brugte farve skrives til filen.

E. Luk filen og lås den op.

I punkt D får du brug for funktionen truncate til at nulstille filen.


> Jeg kunne kopiere det og sætte ind i mit script og håbe på at det
> virkede, men jeg vil helst kunne fårsto hvad der foregik

Det ville nok ikke virke, det var ret meget bare rystet ud af ærmet.


--
Peter Makholm | Perhaps that late-night surfing is not such a
peter@makholm.net | waste of time after all: it is just the web
http://hacking.dk | dreaming
| -- Tim Berners-Lee

Kim Emax (16-08-2003)
Kommentar
Fra : Kim Emax


Dato : 16-08-03 00:43

Peter Makholm wrote:

> Det svære er helt klart punkt 1. En teknisk mere enkel måde at gøre
> det på kunne være at vedligehold en fil men en liste over ledige
> farver, en farve på hver linje. Så kommer punkt et til at skulle løses
> ale følgende:

Hvorfor ikke bare poppe et array? Og så f.eks. løse det ved at finde
størrelsen på farve arrayet og returnere det til rand funktionen? (10 første
gang, næste gang 9, så 8 osv.)

--
Take Care
Kim Emax - Freelance programmør - opgaver modtages
http://www.emax.dk - http://www.ayianapa.dk
Køb din vin online på http://www.gmvin.dk,
Danmarks måske mest avancerede VinWebShop



Peter Makholm (16-08-2003)
Kommentar
Fra : Peter Makholm


Dato : 16-08-03 08:53

"Kim Emax" <newsgroup@remove-emax.dk> writes:

> Hvorfor ikke bare poppe et array? Og så f.eks. løse det ved at finde
> størrelsen på farve arrayet og returnere det til rand funktionen? (10 første
> gang, næste gang 9, så 8 osv.)

Det blev ikke sagt eksplicit med ud fra den eksisterende kode antog
jeg det var noget CGI-lignende noget hvor det var en tilstand der
skulle bevares mellem flere kald af scriptet.

Hvis alt foregår i samme kald af scriptet er alt selvfølgelig meget
lettere.

--
Peter Makholm | I laugh in the face of danger. Then I hide until
peter@makholm.net | it goes away
http://hacking.dk | -- Xander

Flemming Hansen (16-08-2003)
Kommentar
Fra : Flemming Hansen


Dato : 16-08-03 15:39

Hej igen

Jeg har nået frem til 2 foreach løkke. Teoretisk skulle de løse mit problem,
men det virker ikke som det skal. Jeg skal igen bruge jeres hjælp. Jeg har
brugt Peters metode til random farve vælger. Jeg sender bare et array og der
kommer en tilfældig farve ud. Men jeg har stadigvæk problem med at checke om
farven er i brug. Til formålet har jeg vælgt følgende:

foreach (@users){
if($_ ne '.' && $_ ne '..'){
open(FILE, "$db/user/$_") || die "can't open user data file";
lock(FILE);
@user_data = <FILE>;
unlock(FILE);
close(FILE);
}
chomp(@user_data);
push(@used, $user_data[5]);
}

i ovenstående kode laver jeg et array af brugte farver.

i det følgende åbner jeg en dummy file for at se om indholdet af arrays er
det jeg vil have. array'et @color indeholder farve listen og @used
indeholder de brugte. Udfara det skal funktionen sammenligne de to arrays og
dem der ikke blev brugt skal gemmes i et nyt array kaldt @new_color.

open(FILE, ">$chat_db/color.txt") || die "can't open color data file";
lock(FILE);

foreach $dummy_color (@color){
foreach $dummy_used (@used){
if($dummy_color eq $dummy_used){
print FILE "- $dummy_color -\n";
next;

}else{
print FILE "-not used $dummy_color -\n";
push(@new_color, $dummy_color);
last;
}
}
}
unlock(FILE);
close(FILE);

Kan nogen se noget fejl i ovenstående løkke? Jeg får altså kun udgang i ELSE
delen, og det giver hele @color i stedet for dem der ikke er brugt. Har I
noget forslag? Jeg har prøvet "grep" uden held... Tak på forhånd...



Lars Balker Rasmusse~ (16-08-2003)
Kommentar
Fra : Lars Balker Rasmusse~


Dato : 16-08-03 17:34

"Flemming Hansen" <dsl34257@vip.cybercity.dk> writes:
> Jeg har nået frem til 2 foreach løkke. Teoretisk skulle de løse mit problem,
> men det virker ikke som det skal. Jeg skal igen bruge jeres hjælp. Jeg har
> brugt Peters metode til random farve vælger. Jeg sender bare et array og der
> kommer en tilfældig farve ud. Men jeg har stadigvæk problem med at checke om
> farven er i brug. Til formålet har jeg vælgt følgende:
>
> foreach (@users){
> if($_ ne '.' && $_ ne '..'){
> open(FILE, "$db/user/$_") || die "can't open user data file";
> lock(FILE);
> @user_data = <FILE>;
> unlock(FILE);
> close(FILE);
> }
> chomp(@user_data);
> push(@used, $user_data[5]);
> }
>
> i ovenstående kode laver jeg et array af brugte farver.

Er du sikker på at farven er på 6. linie? Er du sikker på at der ikke
er ekstra whitespace på linien? Andet støj? Er du sikker på at der
ikke er ekstra whitespace i din color-liste?a

Du siger jo ikke hvordan user-filerne ser ud.

En bedre metode er i øvrigt at gemme de brugte farver i en hash:

++$used{$user_data[5]};


> foreach $dummy_color (@color){
> foreach $dummy_used (@used){
> if($dummy_color eq $dummy_used){
> print FILE "- $dummy_color -\n";
> next;
>
> }else{
> print FILE "-not used $dummy_color -\n";
> push(@new_color, $dummy_color);
> last;
> }
> }
> }

Med en hash kan ovenstående se således ud:

foreach $dummy_color (@color){
if ($used{$dummy_color}){
print FILE "- $dummy_color -\n";
next;
}
else {
print FILE "-not used $dummy_color -\n";
push(@new_color, $dummy_color);
last;
}
}

> Kan nogen se noget fejl i ovenstående løkke? Jeg får altså kun udgang i ELSE
> delen, og det giver hele @color i stedet for dem der ikke er brugt. Har I
> noget forslag? Jeg har prøvet "grep" uden held... Tak på forhånd...

Prøv at printe meget mere info ud i din log-fil - nogle gange bliver
man lidt overrasket over hvad der faktisk er i sine variable.

Ellers prøv at poste et eksempel på de data der er i dine variable,
ellers er det lidt svært at forklare hvad der går galt.
--
Lars Balker Rasmussen Consult::Perl

Flemming Hansen (16-08-2003)
Kommentar
Fra : Flemming Hansen


Dato : 16-08-03 20:28

> > foreach (@users){
> > if($_ ne '.' && $_ ne '..'){
> > open(FILE, "$db/user/$_") || die "can't open user data
file";
> > lock(FILE);
> > @user_data = <FILE>;
> > unlock(FILE);
> > close(FILE);
> > }
> > chomp(@user_data);
> > push(@used, $user_data[5]);
> > }
> >
> > i ovenstående kode laver jeg et array af brugte farver.
>
> Er du sikker på at farven er på 6. linie? Er du sikker på at der ikke
> er ekstra whitespace på linien? Andet støj? Er du sikker på at der
> ikke er ekstra whitespace i din color-liste?a
>
Ja, jeg er sikker på farven er på 6. linje. jeg udskriver indholdet af den
6. linje på skærmen for at checke om den indeholder noget, og den indeholder
altid en farve.

> Du siger jo ikke hvordan user-filerne ser ud.

user filerne består af 7 linjer seperaret af \n f.eks. ser filen sådan ud:
username\n (\n er jo usynligt i filen)
userhost\n
userip\n
user filteret ip\n
user ID\n
user farve\n
time()

>
> En bedre metode er i øvrigt at gemme de brugte farver i en hash:
>
> ++$used{$user_data[5]};

farven er bare en farve kode, hvad er fordelen ved at gemme den i en hash?
hvordan virker ++$used{$user_data[5]} ? den definition har jeg ikke set før


>
>
> > foreach $dummy_color (@color){
> > foreach $dummy_used (@used){
> > if($dummy_color eq $dummy_used){
> > print FILE "- $dummy_color -\n";
> > next;
> >
> > }else{
> > print FILE "-not used $dummy_color -\n";
> > push(@new_color, $dummy_color);
> > last;
> > }
> > }
> > }
>
> Med en hash kan ovenstående se således ud:
>
> foreach $dummy_color (@color){
> if ($used{$dummy_color}){
> print FILE "- $dummy_color -\n";
> next;
> }
> else {
> print FILE "-not used $dummy_color -\n";
> push(@new_color, $dummy_color);
> last;
> }
> }

> Prøv at printe meget mere info ud i din log-fil - nogle gange bliver
> man lidt overrasket over hvad der faktisk er i sine variable.

jeg har ikke adgang til logfilen hvis du tænker på apache log filen. men
hvis det er coor.txt du tænker på her er et eksampel:

-not used 990077 -
-not used cc0066 -
-not used 6600cc -
-not used 00cc66 -
-not used 66cc00 -
-not used ff0033 -
-not used 3399cc -
-not used 996600 -
-not used 123abc -

disse er alle de farve jeg har til rådighed, og ovenstående løkke markerer
dem ikke brugte filer, men 4 af dem er brugt af 4 brugere, o den 5. får
tildelt en af de ovenstående selvom en anden bruger den samme farve.
>
> Ellers prøv at poste et eksempel på de data der er i dine variable,
> ellers er det lidt svært at forklare hvad der går galt.

jeg skriver indholdet af alle variabler på skærmen og har check på indholdet
af dem. Det er derfor jeg kan påstå at der er noget galt





Lars Balker Rasmusse~ (16-08-2003)
Kommentar
Fra : Lars Balker Rasmusse~


Dato : 16-08-03 20:45

"Flemming Hansen" <dsl34257@vip.cybercity.dk> writes:
>> En bedre metode er i øvrigt at gemme de brugte farver i en hash:
>>
>> ++$used{$user_data[5]};
>
> farven er bare en farve kode, hvad er fordelen ved at gemme den i en hash?
> hvordan virker ++$used{$user_data[5]} ? den definition har jeg ikke set før
>

%used er en hash, $user{noget} slår "noget" op i hashen. Her er
"noget" så $user_data[5], og ++ forhøjer $user{$user_date[5]} med en
(så den er "true").

> jeg har ikke adgang til logfilen hvis du tænker på apache log filen. men
> hvis det er coor.txt du tænker på her er et eksampel:

Det var det. Prøv at printe
join "--", @color, "\n"
i filen også.

>> Ellers prøv at poste et eksempel på de data der er i dine variable,
>> ellers er det lidt svært at forklare hvad der går galt.
>
> jeg skriver indholdet af alle variabler på skærmen og har check på indholdet
> af dem. Det er derfor jeg kan påstå at der er noget galt

Men du har stadig ikke fortalt os hvad det er der er i dine variable.
--
Lars Balker Rasmussen Consult::Perl

Michael Nyvang (21-08-2003)
Kommentar
Fra : Michael Nyvang


Dato : 21-08-03 22:34

Lars Balker Rasmussen wrote:
> Men du har stadig ikke fortalt os hvad det er der er i dine variable.

Den lader vi stå til eftertiden. Stor visdom.

Mvh,
Michael

Der i øvrigt ikke kan lade være med at give denne version af brugerfarvning,
hvoraf den ene er afprøvet i praksis (skal være usagt hvilken):

Der er basalt to måder, den hurtige og den lidt mere langsigtede.

1. Idet man opdager en bruger, skynder man sig til en velassorteret farvehandel
påfører sig bind for øjnene og vælger den sidste bøtte restmaling fra hylderne
(husk altid den sidste, ellers er farverne ikke unikke). Man skynder sig nu
tilbage til brugeren og påfører farven.

Jeg vil her overlade det som en øvelse til læseren, hvordan man sikrer sig at
man påfører farven på den rette bruger og ikke blot en tilfældigt forbipasserende.

2. Den anden måde kræver lidt forberedelse:

Man køber en pakke kondomer og klipper omhyggeligt hul i hvert eksemplar. Derpå
skynder man sig til en velassorteret metropol. Her påfører man sig bind for øjnene
og går ud i det vilde natteliv. Når der spørges undrende til bindet for øjnene svares:
"Det er for at jeg bedre kan se dig" - man vil straks blive opfattet som en meget
spændende og excentrisk guru og effekten vil ikke udeblive.

En generation senere vil man have en række nye brugere i tilfældige farver.

Søg
Reklame
Statistik
Spørgsmål : 177428
Tips : 31962
Nyheder : 719565
Indlæg : 6407936
Brugere : 218877

Månedens bedste
Årets bedste
Sidste års bedste