Avatar billede Slettet bruger
08. juli 2011 - 11:12 Der er 4 kommentarer og
1 løsning

Grupper i grupper - perfekt algoritme ?

Jeg grubler over en udviddelse af adgangssystemet i mit community-halløj.
Adgang til "noget" gives til ét iD: en person eller en gruppe.

Grupperne styrer brugerne selv, og de indeholder selvfølgelig personer.
Men, "fladt" som det er, ryger man let ud i et virvar af næsten ens grupper og lange navne : (

Så jeg ønsker at grupperne også kan indeholde andre grupper.

F.eks:
Adgang til "min have" gives til gruppen Alle_jeg_kender.
Alle_jeg_kender har 2 medlemmer:
Familien: Blandet gruppe med 3 medlemmer
    Konen: person (vist nok)
    Ungerne: gruppe med 3 medlemmer (alle personer)
    De_gamle: gruppe med 2 medlemmer (begge grupper)
        Mine_rødder: Gruppe (5 personer)
        Svigermekanikken: Gruppe (72 personer + 19 grupper - et mareridt i skal spares for!)
Vennerne: gruppe med 2 medlemmer (begge grupper)
    Skolekammerater: gruppe med 20 medlemmer (alle personer)
    Kollegaer: gruppe med 2 medlemmer (begge grupper)
        Soldaterkammerater: Gruppe 48 personer (biologisk set)
        Arbejdskollegaer: gruppe af grupper
            Det_gamle_job: 8 personer
            Firmaet: 2 grupper
                Cheferne: personer
                Medarbejdere: 3 grupper
                    Sælgere: 9 personer
                    Supportere: 4 personer
                    Udviklere: 2 grupper...
                        ....
                        ....
                   
Altså en "bundløs" træstruktur (hvor der KAN eksistere "loops")

Jeg har en lumsk mistanke om at andre har løst denne udfordring.
- og at det kan løses både skidt, godt og Perfekt : )

I øjeblikket (uden grupper i grupper) har jeg to tabeller:
dbGruppe: GruppeID, gruppenavn...
dbMedlem: GruppeID, PersonID


Der er basalt 3 opgaver:
#1: Er personX medlem af gruppeY ?
#2: Hvilke grupper er personX medlem af ?
#3: Hvilke personer er medlem af gruppeY ?

Så der bliver tale om nogle rekursive funktioner (med et global array (imod loops)).
- Men jeg er i tvivl om den en bedste tabelstruktur:
Som nu, men tillade GruppeID'er i PersonID-feltet (kan skelnes middelbart)
Eller om jeg skal indføre en ny Grupper_i_gruppe tabel...

Gode ideer/indsigt/erfaringer/algoritmer (links til)?
Avatar billede magic-mouse Novice
08. juli 2011 - 13:09 #1
Jeg tror du skal kigge nærmere på en recursiv træstruktur som du allerede er inde på, når du så laver din funktion skal den se ud nogenlunde sådan her:

sti[] = array()
int trin = 0;
func f(node)
{
trin++
sti[trin] = node.navn
hvis (node har barn)
{
  hvis(node.barn er gruppe)
  {
    f(node.gruppe)
  }
  hvis(node.barn er person)
  {
    skriv(person.navn)
    skriv(sti)
  }
}
}
Avatar billede Slettet bruger
08. juli 2011 - 16:48 #2
#1 tak. men det ser ikke ud som om du tager højde for muligheden af endeløse loops?

Jeg er kommet frem til følgende løsning af opgave #1
$adgang = isMember( $adgangsGiver, $personID, true);
$tjek = array();

function isMember($grp, $person, $start)
    {    global $tjek;

    if ($grp == $person) return true;

    if (!isGrp($grp)) return false;

    if ($start)
        $tjek = array( $grp );
    else
        aray_push( $tjek, $grp );

    $mems = getMembers($grp); // select memberID from dbMedlem where gruppeID = $grp

    if (in_array( $person, $mems ) return true;

    for ($i=0;$i<count($mems);$i++)
        if (isGrp( $mems[$i] ))
            if (!in_array( $mems[$i], $tjek )
                if (isMember( $mems[$i], $person, false))
                    return true;
    return false;
    }
Som jeg ikke tror kan gøres mere effektivt.. ?

Videre med #2 og #3...
Avatar billede Slettet bruger
08. juli 2011 - 17:36 #3
Opgave #3 Alle personer som er medlem (direkte eller nedarvet) af $grp
$all = array(); $tjek = array();

function allMembers( $grp, $start = true)
    {    global $all, $tjek;

    if (!isGrp($grp)) return array($grp);

    if ($start)
        {
        $tjek=array();
        $all=array();
        }
    else
        $tjek[] = $grp;

    $mems = getMembers( $grp ); // select memberID from dbMedlem where gruppeID = $grp

    for ($i=0; $i<count($mems); $i++)
        if (isGrp( $mems[$i] ))
            allMembers( $mems[$i], false );
        else
            $all[] = $mems[$i];

    if ($start) // oprindeligt kald
        return $all;
    }
Avatar billede Slettet bruger
08. juli 2011 - 22:13 #4
Så, nu er de er (vist) syntax OK, men ikke testet ordentligt (skal liige have Ui på plads først):
// grupper i grupper (aldrig direkte medlem af sig selv!)

$_tools_tjek = array();
$_tools_alle = array();

function isMember($grp, $prs, $start = true)
    {    global $_tools_tjek;

    if ($grp == $prs) return true; // aldrig ved rekursion

    if (!isGRP($grp)) return false;

    if ($start)
        $_tools_tjek = array( $grp );
    else
        $_tools_tjek[] = $grp;

    $result = runSQL("SELECT Medlem FROM GRPm WHERE GiD=?",array("i",$grp));
    if (is_string($result))
        { /* SHIT fejl, bum bum, returnerer false */ }
    else
        for ($i=0; $i<count($result); $i++)
            if ($result[$i]['Medlem'] == $prs) return true;
        else
            if (isGRP( $result[$i]['Medlem'] ))
                if ($start || !in_array( $result[$i]['Medlem'], $_tools_tjek ))
                    if (isMember( $result[$i]['Medlem'], $prs, false))
                        return true;
    return false;
    }


function allMembers( $grp, $start = true)
    {    global $_tools_alle, $_tools_tjek;

    if (!isGRP($grp)) return array($grp); // vil næppe forekomme..

    if ($start)
        {
        $_tools_tjek = array();
        $_tools_alle = array();
        }
    else
        $_tools_tjek[] = $grp;

    $result = runSQL("SELECT Medlem FROM GRPm WHERE GiD=?",array("i",(int)$grp));
    if (is_string($result))
        { /* SHIT fejl. Nå, tilføjer ingen (i stilhed..) */ }
    else
        for ($i=0; $i<count($result); $i++)
            if (isGRP( $result[$i]['Medlem'] ))
                allMembers( $result[$i]['Medlem'], false );
            else
                $_tools_alle[] = $result[$i]['Medlem'];

    if ($start) // oprindeligt kald
        return $_tools_alle;
    }


function allGroups( $prs, $start = true)
    {    global $_tools_alle, $_tools_tjek;

    if ($start)
        {
        $_tools_tjek = array();
        $_tools_alle = array();
        }
    else
        $_tools_tjek[] = $prs; // faktisk en gruppe

    $result = runSQL("SELECT GiD FROM GRPm WHERE Medlem=?",array("i",(int)$prs));
    if (is_string($result))
        { /* SHIT fejl. Nå, tilføjer ingen (i stilhed..) */ }
    else
        for ($i=0; $i<count($result); $i++)
            if (!in_array( $result[$i]['GiD'], $_tools_tjek ))
                allGroups( $result[$i]['GiD'], false);

    if ($start)
        return $_tools_alle;
    }
Points til dem der finder alvorlige fejl : )
Avatar billede Slettet bruger
10. juli 2011 - 12:11 #5
Nå, men det ka' jeg da så heldigvis selv : )
// grupper i grupper (aldrig direkte medlem af sig selv!)

$_tools_tjek = array();
$_tools_alle = array();

function isMember($grp, $prs, $start = true)
    {    global $_tools_tjek;

    if ($grp == $prs) return true; // aldrig ved rekursion

    if (!isGRP($grp)) return false;

    if ($start)
        $_tools_tjek = array( $grp );
    else
        $_tools_tjek[] = $grp;

    $result = runSQL("SELECT Medlem FROM GRPm WHERE GiD=?",array("i",$grp));
    if (is_string($result))
        { /* SHIT fejl, bum bum, returnerer false */ }
    else
        for ($i=0; $i<count($result); $i++)
            if ($result[$i]['Medlem'] == $prs) return true;
        else
            if (isGRP( $result[$i]['Medlem'] ))
                if ($start || !in_array( $result[$i]['Medlem'], $_tools_tjek ))
                    if (isMember( $result[$i]['Medlem'], $prs, false))
                        return true;
    return false;
    }


function allMembers( $grp, $start = true)
    {    global $_tools_alle, $_tools_tjek;

    if (!isGRP($grp)) return array($grp); // vil næppe forekomme..

    if ($start)
        { $_tools_tjek = array(); $_tools_alle = array(); }
    else
        $_tools_tjek[] = $grp;

    $result = runSQL("SELECT Medlem FROM GRPm WHERE GiD=?",array("i",(int)$grp));
    if (is_string($result))
        { /* SHIT fejl. Nå, tilføjer ingen (i stilhed..) */ }
    else
        for ($i=0; $i<count($result); $i++)
            if (isGRP( $result[$i]['Medlem'] ))
                {
                if (!in_array( $result[$i]['Medlem'], $_tools_tjek ))
                    allMembers( $result[$i]['Medlem'], false );
                }
            else
                if (!in_array( $result[$i]['Medlem'], $_tools_alle ))
                    $_tools_alle[] = $result[$i]['Medlem'];

    if ($start) // oprindeligt kald
        return $_tools_alle;
    }

function allGroups( $prs, $start = true)
    {    global $_tools_alle, $_tools_tjek;


    if ($start)
        { $_tools_tjek = array(); $_tools_alle = array(); }
    else
        $_tools_tjek[] = $prs; // faktisk en gruppe

    $result = runSQL("SELECT GiD FROM GRPm WHERE Medlem=?",array("i",(int)$prs));
    if (is_string($result))
        { /* SHIT fejl. Nå, tilføjer ingen (i stilhed..) */ }
    else
        for ($i=0; $i<count($result); $i++)
            if (!in_array( $result[$i]['GiD'], $_tools_tjek ))
                {
                $_tools_alle[] = $result[$i]['GiD'];
                allGroups( $result[$i]['GiD'], false);
                }

    if ($start)
        return $_tools_alle;
    }
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester